2010-02-28 18 views
6

Bu uzantı yöntemini yazdım:Genel bir uzantı yöntemini dinamik olarak nasıl çağırırım?

public static DataTable ToDataTable<T>(this IList<T> list) 
{...} 

Derleme zamanında bilinen bir türle çağrılırsa iyi çalışır:

DataTable tbl = new List<int>().ToDataTable(); 

Ancak, genel tür bilinmiyorsa nasıl çağırılır?

object list = new List<int>(); 
... 
tbl = Extension.ToDataTable((List<object>)list); // won't work 
+0

Neden List '' döküm mı? "Listeniz" bir "" Listesi, yayınlama başarılı olmaz. – Vlad

+0

Derleme zamanında, ne tür bir liste olduğunu bilmediği için: “” Listesini bilmiyor. Bir temel sınıfa (ki, haklı olarak not edersiniz, işe yaramaz, çünkü '' '' '' int '' object' ile uyumlu olsa bile 'List ' ile uyumlu değildir. . – itowlson

cevap

9

ortaya çıkar - Liste türü olan eleman tipi parametresinde covariant değil. Ne yazık ki jenerik yöntemin bir daktilo sürümü almak ve yansıma kullanarak aramak gerekir:

Type listItemType = typeof(int); // cheating for simplicity - see below for real approach 
MethodInfo openMethod = typeof(Extension).GetMethod("ToDataTable", ...); 
MethodInfo typedMethod = openMethod.MakeGenericMethod(typeof(listItemType)); 
typedMethod.Invoke(null, new object[] { list }); 

alternatif IList yerine IList<T> kabul Uzantınız yönteminin bir sürümünü oluşturmak için olabilir. List<T> sınıf olmayan bu genel arabirimi yanı sıra genel arabirimi uygulayan, böylece aramak mümkün olacak:

public static DataTable WeakToDataTable(this IList list) { ... } 

((IList)list).WeakToDataTable(); 

(Gerçekte muhtemelen farklı bir isim yerine bir aşırı kullanmak istiyorum - sadece kullanılarak farklı isim farklı seslenmesini)


diğer bilgiler:. yansıması çözümde, ben liste elemanı tipini nasıl belirleneceği sorunu üzerinden atlanır. Bu ne kadar karmaşık olmak istediğinize bağlı olarak biraz zor olabilir. Eğer nesne (bazı T) bir List<T> olacağını varsayıyoruz, o zaman kolay:

Type listItemType = list.GetType().GetGenericArguments()[0]; 

Eğer IList<T> varsaymak sadece istekli iseniz uygun bulmak gerekir çünkü o zaman, biraz daha zor Arayüz ve bunun genel argümanını alın. Ve GetInterface() öğesini kullanamazsınız çünkü genel bir arabirimin kapalı yapılandırılmış bir örneğini ararsınız. Yani IList<T> bir örneğidir biri için arayan tüm arayüzleri aracılığıyla sürünmek zorunda: meta veri değil, liste içeriği söner çünkü bu boş listeleri için çalışacak

foreach (Type itf in list.GetType().GetInterfaces()) 
{ 
    if (itf.IsGenericType && itf.GetGenericTypeDefinition == typeof(IList<>)) // note generic type definition syntax 
    { 
    listItemType = itf.GetGenericArguments()[0]; 
    } 
} 

.

+0

Sadece "Liste" yerine 'listesini listelemek değil, sorunu çözmek? – Vlad

+0

Elbette, ama soru "jenerik tip bilinmiyorsa ** nasıl diyebilirim?" Diye soruyor **? (vurgu eklendi).Bu yüzden benim notumun gerçekte, yalnızca int olduğunu varsayarak değil, yansımayı kullanarak listItemType'ı bulması gerektiğini de not ettim. – itowlson

+0

Bunu denedim, ancak iki sorunum var: 1. Listenin boş olması durumunda gömülü öğelerin türünü nasıl alacağım? 2. İki ToDataTable() uzantı yöntemim var. IList için nasıl edinilir? –

0

IList<T> arabirimiyle çalışmayı başarabildikten sonra, itowlson gibi önerilen IList arabirimini kullanarak çözdüm. Çünkü _T yönteminin biraz çirkin ama iyi çalışır:

DataTable tbl = ((IList)value).ToDataTable(); 

public static class Extensions 
{ 
    private static DataTable ToDataTable(Array array) {...} 
    private static DataTable ToDataTable(ArrayList list) {...} 
    private static DataTable ToDataTable_T(IList list) {...} 

    public static DataTable ToDataTable(this IList list) 
    { 
     if (list.GetType().IsArray) 
     { 
      // handle arrays - int[], double[,] etc. 
      return ToDataTable((Array)list); 
     } 
     else if (list.GetType().IsGenericType) 
     { 
      // handle generic lists - List<T> etc. 
      return ToDataTable_T(list); 
     } 
     else 
     { 
      // handle non generic lists - ArrayList etc. 
      return ToDataTable((ArrayList)list); 
     }    
    } 
} 
İlgili konular