IQueryable OfType 其中T是运行时类型

我需要能够得到类似以下的东西才能工作:

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

这可能吗? 如果有任何新内容允许,我可以使用.NET 4。

你可以通过反思来调用它:

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

另一种方法是编写自己的OfTypeAndToArraygenerics方法来完成它的两个位,但上面的方法应该可行。

看起来你需要在这里使用Reflection …

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

纯粹在你的问题上使用“generics”,不,这是不可能的。

generics是编译时function,而不是运行时发现。 对于运行时,您需要使用Reflection或Dynamic。

关于什么 …

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

处理多种类型的解决方案是

  public static IQueryable OfTypes(this DbSet query, IEnumerable types ) where TEntity : class { if( types.Count() == 0 ) return query; var lambda = GetOfOnlyTypesPredicate( typeof(TEntity), types.ToArray() ); return query.OfType().Where( lambda as Expression>); } 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 ); 
  object[] entityList = context.Resources .Where(t=> t.GetType() == type) .ToArray();