反思和泛型类型

时间:2008-10-13 07:37:22

标签: c# .net generics reflection

我正在为类构造函数编写一些代码,它循环遍历类的所有属性,并调用一个通用的静态方法,该方法使用外部API中的数据填充我的类。所以我把它作为一个示例类:

public class MyClass{
  public string Property1 { get; set; }
  public int Property2 { get; set; }
  public bool Property3 { get; set; }

  public static T DoStuff<T>(string name){
    // get the data for the property from the external API
    // or if there's a problem return 'default(T)'
  }
}

现在在我的构造函数中我想要这样的东西:

public MyClass(){
  var properties = this.GetType().GetProperties();
  foreach(PropertyInfo p in properties){
    p.SetValue(this, DoStuff(p.Name), new object[0]);
  }
}

所以上面的构造函数会抛出一个错误,因为我没有提供泛型类型。

那么如何传入属性的类型?

3 个答案:

答案 0 :(得分:19)

你想打电话给DoStuff&lt; T&gt; T =每个属性的类型?在这种情况下,“按原样”你需要使用反射和MakeGenericMethod - 即。

var properties = this.GetType().GetProperties();
foreach (PropertyInfo p in properties)
{
    object value = typeof(MyClass)
    .GetMethod("DoStuff")
    .MakeGenericMethod(p.PropertyType)
    .Invoke(null, new object[] { p.Name });
    p.SetValue(this, value, null);
}

但是,这不是很漂亮。实际上,我想知道是否只有更好:

static object DoStuff(string name, Type propertyType);
... and then
object value = DoStuff(p.Name, p.PropertyType);

在这个例子中,泛型给你的是什么?请注意,在反射调用期间,值类型仍将被装箱等 - 甚至装箱isn't as bad as you might think

最后,在许多场景中,TypeDescriptor.GetProperties()比Type.GetProperties()更合适 - 允许灵活的对象模型等。

答案 1 :(得分:7)

你的构造函数代码是这样的:

public MyClass(){
  var properties = this.GetType().GetProperties();
  foreach(PropertyInfo p in properties){
    p.SetValue(this, DoStuff(p.Name), new object[0]);
  }
}

?请注意DoStuff而不是MyClass

如果是这样,问题在于,当他们真的不适用时,你会尝试使用泛型。泛型(点,其中一点)的用途是使用编译时类型安全性。这里你不知道编译时的类型!你可以通过反射调用方法(获取打开的表单,然后调用MakeGenericMethod),但这很难看。

DoStuff首先真的需要通用吗?它是从其他地方使用的吗? PropertyInfo.SetValue的参数只是对象,所以即使你 一般地调用这个方法,你仍然会得到拳击等。

答案 2 :(得分:2)

如果您不从其他地方使用DoStuff,我还建议您编写非通用方法。

也许您创建了通用方法以便能够使用默认值(T)。要在非泛型方法中替换它,可以对值类型使用Activator.CreateInstance(T),对引用类型使用null:

object defaultResult = type.IsValueType ? Activator.CreateInstance(type) : null