简体   繁体   English

可查询类型<T>其中 T 是运行时类型

[英]IQueryable OfType<T> where T is a runtime Type

I need to be able to get something similar to the following to work:我需要能够得到类似于以下内容的工作:

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

Is this possible?这可能吗? I am able to use .NET 4 if anything new in that allows this.如果有任何新内容允许这样做,我可以使用 .NET 4。

You can call it by reflection:您可以通过反射调用它:

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

An alternative would be to write your own OfTypeAndToArray generic method to do both bits of it, but the above should work.另一种方法是编写您自己的OfTypeAndToArray通用方法来完成它的两个部分,但上述方法应该可以工作。

Looks like you'll need to use Reflection here...看起来你需要在这里使用反射......

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

what about ...怎么样...

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

A solution to handle multiple types is处理多种类型的解决方案是

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

Based on @ Jon Skeet 's answer , here's a LINQ extension method:基于@Jon Skeet回答,这里有一个 LINQ 扩展方法:

public static class QueryableExtensions
{
    public static IQueryable<TSource> OfType<TSource>(this IQueryable<TSource> queryable,
        Type runtimeType)
    {
        var method = typeof(Queryable).GetMethod(nameof(Queryable.OfType));
        var generic = method.MakeGenericMethod(new[] { runtimeType });
        return (IQueryable<TSource>)generic.Invoke(null, new[] { queryable });
    }
}
Resource[] entityList = context.Resources
                              .Where(t => t.GetType() == typeof(HumanResource))
                              .ToArray();

Purely on your question to use "Generics", No it is not possible.纯粹针对您使用“泛型”的问题,不,这是不可能的。

Generics is a compile time feature, and not a runtime discovery.泛型是编译时特性,而不是运行时发现。 For runtime, you need to use Reflection or Dynamic.对于运行时,您需要使用反射或动态。

这对我有用...

Type type = queryable.GetType().GenericTypeArguments[0];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM