2011-02-03 82 views
1

我正要通过对反射和泛型的一些文章,我碰到下面的代码来:优势Activator.CreateInstance的

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

您可以添加对文章的引用吗? – 2011-02-03 11:47:12

+0

这是一个人为的例子。也不是很好的一个,命名的选择是一个可怕的。 GetFooInstance不*建议创建* new * Foo。 – 2011-02-03 12:30:13

回答

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 
); 
0

唯一的优点是您可以执行额外的处理。

你可以例如用一些额外的处理来扩展CreateControlInstance<T>方法,这需要执行以前的控制。

然而,当选择的是有绝对

之间
MyButton b = CreateControlInstance<MyButton>(SomeformInstance); 

MyButton b = new MyButton(SomeformInstance); 

没有理由不选择后者。前者会表现得更差,会不必要地混淆你的代码。

2

如果你打算用这种方式创建很多控件,你会注意到你的应用程序运行缓慢。这是因为Activator.CreateInstance比简单的new()慢10000倍。请牢记这一点。