我绝对记得在某个地方看到过使用反射或其他东西这样做的例子。这与用户无法创建的SqlParameterCollection
有关(如果我没弄错的话)。不幸的是再也找不到了。
有人可以在这里分享这个技巧吗?并不是说我认为它是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。
答案 0 :(得分:57)
您可以使用 Activator.CreateInstance 的重载之一来执行此操作:Activator.CreateInstance(Type type, bool nonPublic)
使用true
作为nonPublic
参数。因为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()
{
}
}
答案 1 :(得分:40)
// 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 :(得分:4)
答案 3 :(得分:2)
如果这个类不是你的类,那么听起来就像故意编写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(...));
我的例子不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但你明白了。
答案 4 :(得分:1)
如果您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);
}