2008-10-13 147 views
12

我正在为类构造函数编写一些代码,它循环遍历类的所有属性,并调用一个通用的静态方法,它使用来自外部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]); 
    } 
} 

所以上面的构造函数将抛出一个错误,因为我不供应泛型类型。

那么如何传递属性的类型呢?

+0

对不起的问题是怎么样的混乱,有没有第二个代码的一些错字片段? – smaclell 2008-10-13 07:44:21

回答

19

你想打电话给DoStuff <T> 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更合适() - 允许灵活的对象模型等

7

本来是你的构造函数的代码读取这样的:

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

?请注意0​​而不是MyClass

如果是这样,问题在于您试图在非真正适用的情况下使用泛型。泛型的要点(好,其中一点)是使用编译时类型安全。这里你不知道编译时的类型!你可以通过反射调用该方法(获取开放表单,然后调用MakeGenericMethod),但这非常难看。

DoStuff是否真的需要通用?它是否在其他地方使用? PropertyInfo.SetValue的参数只是对象,所以即使你的可能一般地调用该方法,你仍然会得到拳击等。

2

如果您不从别的地方使用DoStuff,我还建议编写一个非泛型方法。

也许你创建了可以使用默认(T)的通用方法。为了替换在非泛型方法,您可以使用Activator.CreateInstance(T)值类型和空引用类型:

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