如何在 C# 中使用私有构造函数实例化对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/708952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to instantiate an object with a private constructor in C#?
提问by User
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.
任何人都可以在这里分享这个技巧吗?并不是说我认为这是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。
采纳答案by LukeH
// 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);
}
回答by Neil Barnwell
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 dohave 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:
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.
我的示例不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但您明白了。
回答by Jonathan Parker
Is this the question you were after? Activator.CreateInstance with private sealed class
这是你要问的问题吗? 带有私有密封类的 Activator.CreateInstance
回答by Sean
You can use one of the overloads of Activator.CreateInstanceto 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.
使用true
的nonPublic
参数。因为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()
{
}
}
回答by Mr.B
It will also help if your Type
is private
or internal
:
如果您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);
}