How to instantiate an object with a private constructor in C#?

余生长醉 提交于 2019-11-28 08:55:26
// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };

// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };

TheTypeYouWantToInstantiate instance =
    Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);

// ...

public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
    Type t = typeof(T);

    ConstructorInfo ci = t.GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, paramTypes, null);

    return (T)ci.Invoke(paramValues);
}
Sean

You can use one of the overloads of Activator.CreateInstance to do this: Activator.CreateInstance(Type type, bool nonPublic)

Use true for the nonPublic argument. Because true matches a public or non-public default constructor; and false matches only a public default constructor.

For example:

    class Program
    {
        public static void Main(string[] args)
        {
            Type type=typeof(Foo);
            Foo f=(Foo)Activator.CreateInstance(type,true);
        }       
    }

    class Foo
    {
        private Foo()
        {
        }
    }
Jonathan Parker

Is this the question you were after? Activator.CreateInstance with private sealed class

If the class isn't one of yours, then it sounds like the API was deliberately written to prevent this, which means that it's possible your approach isn't what the API writers intended. Take a look at the docs and see if there's a recommended approach to using this class.

If you do have control over the class and want to implement this pattern, then it's typically implemented via a static method on a class. This is a key concept that makes up the Singleton pattern, too.

For example:

public PrivateCtorClass
{
    private PrivateCtorClass()
    {
    }

    public static PrivateCtorClass Create()
    {
        return new PrivateCtorClass();
    }
}

public SomeOtherClass
{
    public void SomeMethod()
    {
        var privateCtorClass = PrivateCtorClass.Create();
    }
}

The SqlCommandParameter stuff is a good example. They expect you to create parameters by calling things like this:

var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));

My example isn't great code because it doesn't demonstrate setting command parameter properties or reuse of parameters/commands, but you get the idea.

It will also help if your Type is private or internal:

 public static object CreatePrivateClassInstance(string typeName, object[] parameters)
    {
        Type type = AppDomain.CurrentDomain.GetAssemblies().
                 SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
        return type.GetConstructors()[0].Invoke(parameters);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!