如何在C#中使用私有构造函数实例化对象?

时间:2022-09-02 08:46:41

I definitely remember seeing somewhere an example of doing so using reflection or something. It was something that had to do with SqlParameterCollection which is not creatable by a user (if I'm not mistaken). Unfortunately cannot find it any longer.

我当然记得在某个地方看到一个使用反射或其他东西这样做的例子。这与SqlParameterCollection有关,不能由用户创建(如果我没记错的话)。不幸的是再也找不到了。

Can anyone please share this trick here? Not that I consider it a valid approach in development, I'm just very interested in the possibility of doing this.

有人可以在这里分享这个技巧吗?并不是说我认为它是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。

5 个解决方案

#1


// 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);
}

#2


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

您可以使用Activator.CreateInstance的重载之一来执行此操作: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.

对nonPublic参数使用true。因为true匹配公共或非公共默认构造函数;和false仅匹配公共默认构造函数。

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()
        {
        }
    }

#3


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

这是你追问的问题吗? Activator.CreateInstance与私人密封类

#4


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.

如果这个类不是你的类,那么听起来就像故意编写API来防止这种情况,这意味着你的方法可能不是API编写者的意图。看看文档,看看是否有推荐的方法来使用这个类。

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.

如果您确实可以控制该类并希望实现此模式,那么它通常通过类上的静态方法实现。这也构成了Singleton模式的关键概念。

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:

SqlCommandParameter的东西就是一个很好的例子。他们希望您通过调用以下内容来创建参数:

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.

我的例子不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但你明白了。

#5


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);
    }

#1


// 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);
}

#2


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

您可以使用Activator.CreateInstance的重载之一来执行此操作: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.

对nonPublic参数使用true。因为true匹配公共或非公共默认构造函数;和false仅匹配公共默认构造函数。

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()
        {
        }
    }

#3


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

这是你追问的问题吗? Activator.CreateInstance与私人密封类

#4


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.

如果这个类不是你的类,那么听起来就像故意编写API来防止这种情况,这意味着你的方法可能不是API编写者的意图。看看文档,看看是否有推荐的方法来使用这个类。

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.

如果您确实可以控制该类并希望实现此模式,那么它通常通过类上的静态方法实现。这也构成了Singleton模式的关键概念。

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:

SqlCommandParameter的东西就是一个很好的例子。他们希望您通过调用以下内容来创建参数:

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.

我的例子不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但你明白了。

#5


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);
    }