我绝对记得在某处看到一个使用反射或其他东西的例子。这是与用户无法创建的事情有关SqlParameterCollection
(如果我没记错的话)。可惜再也找不到了。
有人可以在这里分享这个技巧吗?并不是说我认为它是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。
我绝对记得在某处看到一个使用反射或其他东西的例子。这是与用户无法创建的事情有关SqlParameterCollection
(如果我没记错的话)。可惜再也找不到了。
有人可以在这里分享这个技巧吗?并不是说我认为它是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。
您可以使用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()
{
}
}
// 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);
}
如果该类不是您的类,那么听起来 API 是故意编写的以防止这种情况发生,这意味着您的方法可能不是 API 编写者的意图。查看文档,看看是否有推荐的方法来使用这个类。
如果您确实可以控制该类并希望实现此模式,那么它通常通过类上的静态方法来实现。这也是构成单例模式的一个关键概念。
例如:
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
如果您的isprivate
或,它也会有所帮助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);
}