2013-11-27 75 views
1

我正在與我的.net 3.5項目中有一堆(約20-30)集合類型接口的COM庫。這些類中的每一個都公開了名爲Count的屬性以及名爲ItemByIndex(int)GetEnumerator()(其類型爲System.Collections.IEnumerator)的方法。通用擴展方法,但通用方法,但沒有繼承

但是,這些接口中的每一個接口都是自己實現的,而不是共同的父類。

有沒有辦法編寫一個通用的擴展方法,將集合對象轉換爲列表<>?這是我目前正在做的,但我有20個左右的方法複製和粘貼。

public static List<iml.IManDocument> ToList(this iml.IManDocuments source) 
{ 
    List<iManDocument> results = new List<iManDocument>(source.Count); 
    for (int i = 1; i <= source.Count; i++) 
    { 
     results.Add((iml.IManDocument)source.ItemByIndex(i)); 
    } 
    return results; 
} 

回答

1

理想情況下,您應該讓您的類型實現IList<T>IReadOnlyList<T>。不過,我猜你不能這樣做......

您可以使用內置的方法(利用的事實,他們是IEnumerable)做到這一點:

var list = myIManDocuments.Cast<IManDocument>().ToList(); 

你可以用它做dynamic,但是這有缺點,最大的一個問題是你沒有得到任何編譯時檢查你是否在兼容類型中執行此操作。

public static List<T> ToList<T>(dynamic source) 
{ 
    List<T> results = new List<T>(source.Count); 
    for (int i = 1; i <= source.Count; i++) 
    { 
     results.Add(source.ItemByIndex(i)); 
    } 
    return results; 
} 

使用像:

var list = MyUtil.ToList<IManDocument>(myIManDocuments); 
0

List有一個接受IEnumerable參數的構造函數。由於IEnumerable只具有(通用的)GetEnumerator,因此您可以輕鬆地使您的接口從IEnumerable(通用接口)派生並使用List構造函數。

2

不幸的是,您不能在現有方法的基礎上添加擴展方法,也無法將接口動態添加到適合這些接口的類型中(兩者都是非常有用的東西)。

一個選項是爲object添加擴展方法,並使用反射來確定是否存在所需的方法和屬性。

public static List<iml.IManDocument> ToListByReflection(this object source) 
{ 
    var type = source.GetType(); 
    var countProperty = type.GetProperty("Count"); 
    var itemByIndexMethod = type.GetMethod("ItemByIndex", new[] { typeof(int) }); 

    if (countProperty == null || itemByIndexMethod == null) 
    { 
     throw new Exception("Type does not offer required methods."); 
    } 

    var count = countProperty.GetValue(source); 
    var results = new List<iManDocument>(count); 
    for (int i = 1; i <= count; i++) 
    { 
     results.Add((iml.IManDocument)itemByIndexMethod.Invoke(source, new object[] { i }); 
    } 

    return results; 
} 

爲了獲得更好的性能,您甚至可以緩存每種不同類型的屬性和方法信息。

但只是寫一個像你一樣的方法在我看來真的是更好的選擇。它更清晰,它在編譯時是類型安全的(值得很多!),並且比反射更快。這只是一次寫入每種類型,而且大部分都是複製粘貼。