[英]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.