Esto se produce porque un List<int>
no es un List<object>
- el tipo de lista no es covariante en su parámetro de tipo de elemento. Desafortunadamente usted necesita para obtener una versión mecanografiada del método genérico y lo llaman utilizando la reflexión:
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 });
Una alternativa puede ser la creación de una versión de su método de extensión que acepte IList
en lugar de IList<T>
. La clase List<T>
implementa esta interfaz no genérico, así como la interfaz genérica, por lo que será capaz de llamar a:
public static DataTable WeakToDataTable(this IList list) { ... }
((IList)list).WeakToDataTable();
(En realidad lo que probablemente utilice una sobrecarga en lugar de un nombre diferente - sólo usar un nombre diferente para llamar a los diferentes tipos)
Más información:. En la solución de reflexión, me he saltado sobre el problema de cómo determinar el tipo de lista de elementos. Esto puede ser un poco complicado según lo sofisticado que desee obtener. Si usted está asumiendo que el objeto será una List<T>
(para algunos T) entonces es fácil:
Type listItemType = list.GetType().GetGenericArguments()[0];
Si sólo estás dispuesto a asumir IList<T>
entonces es un poco más difícil, porque hay que localizar el apropiado interfaz y obtener el argumento genérico de eso. Y no puede usar GetInterface() porque está buscando una instancia cerrada y construida de una interfaz genérica. Así que hay que arrastrarse a través de todas las interfaces en busca de uno que es una instancia de 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];
}
}
Esto funcionará para las listas vacías porque sale de los metadatos, no el contenido de la lista.
¿Por qué echaron a '' Lista
Porque no sabe en tiempo de compilación qué tipo de lista tiene: no sabe que es 'List'. Está tratando de sortearlo lanzando a una clase base (que, como bien anotará, no funcionará porque 'List ' no es compatible con 'List