如何在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(...));
我的例子不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但你明白了。
如果您的Type
是private
或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); }