IQueryable OfType <T>где T - тип времени выполнения - PullRequest
25 голосов
/ 08 сентября 2010

Мне нужно, чтобы что-то похожее на следующее работало:

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

Возможно ли это? Я могу использовать .NET 4, если что-то новое в этом позволяет.

Ответы [ 6 ]

37 голосов
/ 08 сентября 2010

Вы можете назвать это отражением:

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();

Альтернативой может быть написание собственного OfTypeAndToArray универсального метода для выполнения обоих его битов, но вышеприведенное должно работать.

8 голосов
/ 08 сентября 2010

Похоже, вам нужно использовать Reflection здесь ...

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();
1 голос
/ 27 февраля 2016

а как же ...

    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 }));
    }
0 голосов
/ 11 апреля 2018

Решение для обработки нескольких типов:

        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 );
0 голосов
/ 08 сентября 2010

Чисто по вашему вопросу используйте "Дженерики", Нет, это невозможно.

Обобщения - это функция времени компиляции, а не обнаружение во время выполнения. Для выполнения вам нужно использовать Reflection или Dynamic.

0 голосов
/ 08 сентября 2010
 object[] entityList = context.Resources
                              .Where(t=> t.GetType() == type)
                              .ToArray();
...