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

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

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

// 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(paramTypes, paramValues); // ... public static T Construct(Type[] paramTypes, object[] paramValues) { Type t = typeof(T); ConstructorInfo ci = t.GetConstructor( BindingFlags.Instance | BindingFlags.NonPublic, null, paramTypes, null); return (T)ci.Invoke(paramValues); } 

您可以使用Activator.CreateInstance的重载之一来执行此操作: Activator.CreateInstance(Type type, bool nonPublic)

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

例如:

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

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

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

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

例如:

 public PrivateCtorClass { private PrivateCtorClass() { } public static PrivateCtorClass Create() { return new PrivateCtorClass(); } } public SomeOtherClass { public void SomeMethod() { var privateCtorClass = PrivateCtorClass.Create(); } } 

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

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

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

如果您的Typeprivateinternal它也会有所帮助:

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