2010-09-03 31 views
2

我有一個函數,它使用反射從對象B設置對象A的屬性。 有一點,我需要實例化一個通用集合。但是,我無法得到它的工作。這裏是我現在有:使用反射創建一個通用列表

IList list = destProperty.PropertyType.GetGenericTypeDefinition() 
       .MakeGenericType(destProperty.PropertyType.GetGenericArguments()) 
       .GetConstructor(Type.EmptyTypes) 
       .Invoke(null) as IList; 

我想設置destProperty的值。它必須是列表 在運行時,destProperty的類型爲ICollection <>。我認爲發生的事情是因爲ICollection是一個接口,它沒有構造函數。那麼實例化它的正確方法是什麼?

謝謝!

回答

2

我已經重新編寫代碼,變成一個例子的形式(希望匹配你想要做什麼!=),試圖使其更清晰的問題是什麼:

public class Program 
{ 
    public struct MyType 
    { 
     public ICollection<string> MyProperty { get; set; } 
    } 
    static void Main(string[] args) 
    { 
     var type = typeof(MyType); 
     var properties = type.GetProperties(); 
     var destProperty = properties[0]; 

     var genericTypeDefinition = destProperty.PropertyType.GetGenericTypeDefinition(); 
     var madeGenericType = genericTypeDefinition.MakeGenericType(destProperty.PropertyType.GetGenericArguments()); 
     var ctor = madeGenericType.GetConstructor(Type.EmptyTypes); 
    } 
} 

如果你把一個斷點在倒數第二支柱,你會看到ctor回來爲null,這是因爲,當你正確地推測,ICollection<T>沒有任何構造函數,由於它是一個接口。

正因爲如此,這樣做並沒有「超級通用」的方式,因爲沒有固有的方式來說「在這種情況下使用ICollection<T>的最佳實施方式」。根據你從反思中得到的信息,你需要做出這個決定和new之一。

0

你不能實例化一個接口。 可以實例化一個實現該接口的泛型類型。在你的情況下,你需要獲得代表泛型列表<>的Type,然後調用MakeGenericType。

假設您知道List將始終有效。如果沒有,我想你可以搜索實現這個接口的類型,但是如何選擇一個接口並確保它有一個無參數的構造函數,這對我來說似乎很複雜。看起來像在這種情況下獲取對象的實際類型而不是接口更容易。

0

一種技術是聲明一個靜態方法,它採用與您要創建的列表相同的泛型參數。然後你可以從屬性中調用參數來調用該方法。

Type interfaceType = destProperty.PropertyType; 
return typeof(MyClass) 
    .GetMethod("CreateList", BindingFlags.NonPublic | BindingFlags.Static) 
    .MakeGenericMethod(interfaceType.GetGenericArguments()) 
    .Invoke(null, new object[] { }); 

private static IList CreateList<T>() 
{ 
    return new List<T>(); 
}