Dzieje się tak dlatego, że List<int>
nie jest List<object>
- typ lista nie jest kowariantna w jego parametr typu elementu. Niestety trzeba by dostać wpisane wersję metody rodzajowe i wywołać ją przy użyciu odbicia:
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 });
Alternatywą może być stworzenie wersji metodę rozszerzenia, które akceptuje IList
zamiast IList<T>
. Klasa List<T>
implementuje ten interfejs nierodzajową jak również interfejs rodzajowe, dzięki czemu będą mogli zadzwonić:
public static DataTable WeakToDataTable(this IList list) { ... }
((IList)list).WeakToDataTable();
(W rzeczywistości ty pewnie użyć przeciążenie zamiast inną nazwą - tylko przy użyciu inna nazwa zawołać różne rodzaje)
Więcej informacji:. W rozwiązaniu refleksji, że pomijane problem, jak określić typ elementu listy. Może to być nieco trudne, w zależności od tego, jak wyrafinowane chcesz uzyskać. Jeśli zakładamy, że obiekt będzie List<T>
(dla pewnego t) to proste:
Type listItemType = list.GetType().GetGenericArguments()[0];
jeśli jesteś tylko skłonni zakładać IList<T>
to jest to nieco trudniejsze, ponieważ trzeba znaleźć odpowiednie interfejs i uzyskać ogólny argument z tego. I nie możesz użyć funkcji GetInterface(), ponieważ szukasz zamkniętej instancji ogólnego interfejsu. Więc trzeba czołgać przez wszystkie interfejsy poszukuje dla jednego, który jest instancją IList<T>
:
foreach (Type itf in list.GetType().GetInterfaces())
{
if (itf.IsGenericType && itf.GetGenericTypeDefinition == typeof(IList<>)) // note generic type definition syntax
{
listItemType = itf.GetGenericArguments()[0];
}
}
To będzie pracować dla pustych list, ponieważ gaśnie metadanych, a nie zawartość listy.
Dlaczego rzutujesz na 'List
Ponieważ nie wie, w czasie kompilacji, jakiego rodzaju list ma: nie wie, że to 'List'. Próbuje ominąć to poprzez rzutowanie na klasę podstawową (co, jak słusznie zauważysz, nie zadziała, ponieważ 'Lista ' nie jest kompatybilna z 'Listą