Это происходит потому, что List<int>
не List<object>
- тип списка не ковариантны в параметре типа элемента. К сожалению, вам нужно будет получить набранную версию универсального метода и назовите его с помощью отражения:
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 });
Альтернативы может быть, чтобы создать версию методы расширения, который принимает IList
, а не IList<T>
. List<T>
класс реализует этот необщего интерфейс, а также общий интерфейс, так что вы будете в состоянии назвать:
public static DataTable WeakToDataTable(this IList list) { ... }
((IList)list).WeakToDataTable();
(На самом деле вы, вероятно, использовать перегрузку, а не с другим именем - только с помощью другое имя, чтобы вызвать различные типы)
Дополнительная информация:. в решении отражения, я пропустил над проблемой, как определить тип элемента списка. Это может быть немного сложнее в зависимости от того, насколько вы изощренны. Если Вы предполагаете, что объект будет List<T>
(для некоторого Т), то это легко:
Type listItemType = list.GetType().GetGenericArguments()[0];
Если вы только готовы взять на себя IList<T>
то это немного сложнее, потому что вам нужно найти соответствующий интерфейс и получить общий аргумент от этого. И вы не можете использовать GetInterface(), потому что вы ищете закрытый сконфигурированный экземпляр универсального интерфейса. Таким образом, вы должны пресмыкаться через все интерфейсы ищет тот, который является экземпляром 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];
}
}
Это будет работать для пустых списков, поскольку она идет от метаданных, а не содержание списка.
Почему вы приводите в '' Список
Потому что он не знает во время компиляции, какой у него тип списка: он не знает, что это 'List'. Он пытается обойти это, отбрасывая базовый класс (который, как вы правильно заметили, не будет работать, потому что 'List ' несовместим с 'List