c# linq reflection iqueryable

c# - IQueryable OfType<T> donde T es un tipo de tiempo de ejecución



linq reflection (6)

Parece que necesitarás usar Reflection aquí ...

public static IEnumerable<object> DyamicOfType<T>( this IQueryable<T> input, Type type) { var ofType = typeof(Queryable).GetMethod("OfType", BindingFlags.Static | BindingFlags.Public); var ofTypeT = ofType.MakeGenericMethod(type); return (IEnumerable<object>) ofTypeT.Invoke(null, new object[] { input }); } Type type = // ...; var entityList = context.Resources.DynamicOfType(type).ToList();

Necesito poder hacer que funcione algo similar a lo siguiente:

Type type = ??? // something decided at runtime with .GetType or typeof; object[] entityList = context.Resources.OfType<type>().ToList();

es posible? Puedo usar .NET 4 si hay algo nuevo en eso que lo permita.


Puedes llamarlo por reflexión:

MethodInfo method = typeof(Queryable).GetMethod("OfType"); MethodInfo generic = method.MakeGenericMethod(new Type[]{ type }); // Use .NET 4 covariance var result = (IEnumerable<object>) generic.Invoke (null, new object[] { context.Resources }); object[] array = result.ToArray();

Una alternativa sería escribir su propio método genérico de OfTypeAndToArray para hacer ambos bits, pero lo anterior debería funcionar.


Simplemente en su pregunta para usar "Genéricos", No , no es posible.

Los genéricos son una característica de tiempo de compilación y no un descubrimiento en tiempo de ejecución. Para el tiempo de ejecución, necesita utilizar Reflection o Dynamic.


Una solución para manejar múltiples tipos es

public static IQueryable<TEntity> OfTypes<TEntity>(this DbSet<TEntity> query, IEnumerable<Type> types ) where TEntity : class { if( types.Count() == 0 ) return query; var lambda = GetOfOnlyTypesPredicate( typeof(TEntity), types.ToArray() ); return query.OfType<TEntity>().Where( lambda as Expression<Func<TEntity,bool>>); } public static LambdaExpression GetOfOnlyTypesPredicate( Type baseType, Type[] allowed ) { ParameterExpression param = Expression.Parameter( baseType, "typeonlyParam" ); Expression merged = Expression.TypeIs( param, allowed[0] ); for( int i = 1; i < allowed.Length; i++ ) merged = Expression.OrElse( merged, Expression.TypeIs( param, allowed[i] )); return Expression.Lambda( merged, param );


qué pasa ...

public static IList OfTypeToList(this IEnumerable source, Type type) { if (type == null) throw new ArgumentNullException(nameof(type)); return (IList) Activator.CreateInstance( typeof(List<>) .MakeGenericType(type), typeof(System.Linq.Enumerable) .GetMethod(nameof(System.Linq.Enumerable.OfType), BindingFlags.Static | BindingFlags.Public) .MakeGenericMethod(type) .Invoke(null, new object[] { source })); }


object[] entityList = context.Resources .Where(t=> t.GetType() == type) .ToArray();