Dies geschieht, weil ein List<int>
kein List<object>
ist - die Liste Typ nicht in seinem Element Typparameter kovariant ist. Leider müssen Sie eine typisierte Version der generischen Methode bekommen und es mithilfe von Reflektion nennen:
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 });
Eine Alternative eine Version Ihrer Erweiterung Methode erstellen kann, die IList
statt IList<T>
akzeptiert. Die List<T>
Klasse implementiert diese nicht-generische Schnittstelle sowie die generische Schnittstelle, so können Sie anrufen:
public static DataTable WeakToDataTable(this IList list) { ... }
((IList)list).WeakToDataTable();
(In Wirklichkeit würden Sie vermutlich eine Überlastung, anstatt einen anderen Namen verwenden - nur mit ein anderer Name, die verschiedenen Arten ruft an)
Weitere Informationen:. In der Reflexion Lösung, übersprungen ich über das Problem, wie die Liste Elementtyp zu bestimmen. Dies kann ein bisschen schwierig sein, je nachdem, wie anspruchsvoll Sie erhalten möchten. Wenn Sie davon aus, dass das Objekt ein List<T>
sein (für einige T), dann ist es einfach:
Type listItemType = list.GetType().GetGenericArguments()[0];
Wenn Sie nur bereit sind, zu übernehmen IList<T>
dann ist es etwas schwieriger, weil Sie die entsprechende suchen müssen Schnittstelle und holen Sie sich das generische Argument von diesem. Und Sie können GetInterface() nicht verwenden, da Sie nach einer geschlossen konstruierten Instanz einer generischen Schnittstelle suchen. Also muss man für eine Suche aller Schnittstellen kriechen durch die eine Instanz von 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];
}
}
Dies wird für leere Listen arbeiten, weil es aus den Metadaten geht, nicht in der Liste Inhalt.
Warum Sie 'Liste
Weil er zur Kompilierzeit nicht weiß, welche Art von Liste er hat: Er weiß nicht, dass es 'List' ist. Er versucht es zu umgehen, indem er in eine Basisklasse wirft (was, wie Sie zu Recht bemerken, nicht funktionieren wird, da 'List ' nicht kompatibel mit 'List