我刚刚阅读了一些有关反射和泛型的文章,我发现了以下代码:
public static T CreateControlInstance<T>(FormControl parent)
where T : FormControl
{
T control = GetControlInstance<T>(parent);
//do something with control
}
public static T GetControlInstance<T>(FormControl parent)
{
return (T)Activator.CreateInstance(typeof(T), new object[] { parent });
}
这些方法的用法如下:
MyButton b = CreateControlInstance<MyButton>(SomeformInstance);
许多控件都是以这种方式创建的。我想知道:
Q1 即可。这种方法有哪些优点?
Q2 即可。鉴于对象实例类型在编译时是已知的,这种方法的优点是什么? (我假设按钮和FormControl
以某种方式与System.Windows.Forms.Control
)
修改
我在这里发现了类似的事情
Create instance of generic type?
基本上我想从运行时读取的字符串创建类型(已知类型)?
我想避免使用if-then-else的长列表来创建特定类型的对象,具体取决于字符串。但是没有线索。
任何人都有更好的解决方案,以便可以避免反射来创建已知类型的元素
结束修改
答案 0 :(得分:3)
泛型的问题在于您无法在复杂的构造函数上定义约束。唯一的限制是空构造函数的可用性。
public static T CreateInstance<T>() where T : new()
{
return new T();
}
但是,如果要传递参数,则必须使用其他方法,例如Activator.CreateInstance
。你也可以使用lambda。
public static T CreateInstance<T>(Func<FormControl, T> builder, FormControl parent)
{
return builder(parent);
}
但是你必须为每个不同的对象提供一个特定的lambda来构造你的对象。
MyButton b = CreateInstance<MyButton>(parent => new MyButton(parent), SomeformInstance);
通过使用反射,您可以使代码更简单并自动使用预定义的构造函数。但是通过使用lambda,您可以使用与给定约定不匹配的类,并使用您自己的数据填充其他构造函数参数。
var b2 = CreateInstance<MyOtherButton>(
parent => new MyOtherButton("name", 42, parent), SomeformInstance
);
答案 1 :(得分:2)
如果您打算以这种方式创建大量控件,您会注意到您的应用程序运行缓慢。这是因为Activator.CreateInstance比简单的new()慢10000倍。请记住这一点。
答案 2 :(得分:0)
唯一的好处是您可以执行额外处理。
你可以,例如通过一些额外的处理来扩展CreateControlInstance<T>
方法,这些处理需要进行控制。
然而,当选择在
之间时MyButton b = CreateControlInstance<MyButton>(SomeformInstance);
和
MyButton b = new MyButton(SomeformInstance);
绝对没有理由不选择后者。前者会表现得更糟,并且会不必要地混乱你的代码。