在这种情况下,Activator.CreateInstance的优势

时间:2011-02-03 10:44:06

标签: c# .net generics reflection

我刚刚阅读了一些有关反射和泛型的文章,我发现了以下代码:

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的长列表来创建特定类型的对象,具体取决于字符串。但是没有线索。
 任何人都有更好的解决方案,以便可以避免反射来创建已知类型的元素 结束修改

3 个答案:

答案 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);

绝对没有理由不选择后者。前者会表现得更糟,并且会不必要地混乱你的代码。