2008-10-13 200 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