我尝试在动态数据+ EF网站中实施一些过滤,并使用QueryExtender
和CustomExpression
。在OnQuerying
的{{1}}事件中,我可以访问CustomExpression
(其中e的类型为e.Query
),这是用于从数据库中获取数据的查询。为了过滤数据,我需要对此查询进行更改。
现在此查询的类型为CustomExpressionEventArgs
,其中T仅在运行时已知。我将假设无论T是什么类型,它都将拥有一个名为System.Data.Objects.ObjectQuery<T>
的属性。我需要做的是在这个集合上做一个简单的GameId
LINQ语句,我用该属性过滤。
Where
这样做,现在short GameId = Convert.ToInt16(Session["GlobalGameFilter"]);
Type currentType = e.Query.ElementType;
//ObjectQuery implements IQueryable and I want to cast to ObjectQuery<CurrentType>
MethodInfo method = typeof(Queryable).GetMethod("Cast").MakeGenericMethod(new Type[] { currentType });
var castedQuery = method.Invoke(e.Query, new object[]{e.Query});
的类型为castedQuery
问题在于,为了使用ObjectQuery<currentType>
我需要将其转换为castedQuery.Where()
,我无法将其转换为非通用IEnumerable<currentType>
。
我尝试通过反射调用Where(来自here):
IEnumerable
但是ret总是一个空集合。
编辑:您可以看到我将最后一行中的类型硬编码为放置(仅用于测试),但我当然需要将其作为currentType。
Edit2:如果我试试这个
var whereMethods = typeof(System.Linq.Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(mi => mi.Name == "Where");
MethodInfo whereMethod = null;
foreach (var methodInfo in whereMethods)
{
var paramType = methodInfo.GetParameters()[1].ParameterType;
if (paramType.GetGenericArguments().Count() == 2)
{
whereMethod = methodInfo;
}
}
whereMethod = whereMethod.MakeGenericMethod(currentType);
var ret = whereMethod.Invoke(castedQuery, new object[] { castedQuery, BuildEqFuncFor<Placement>("GameId", GameId) });
它有效,itemGameId实际上得到了我需要的gameId所以问题必须是谓词没有被正确使用。
编辑3:尝试实现通用接口
foreach(var item in castedQuery as IEnumerable)
{
var itemGameId = item.GetType().InvokeMember("GameId", BindingFlags.GetProperty, null, item, null);
}
当我尝试枚举e.Query时遇到错误:public interface IGameId
{
short GameIdGetter { get; }
}
public partial class Placement : IGameId
{
public short GameIdGetter
{
get
{
return this.GameId;
}
}
}
e.Query = e.Query.Cast<IGameId>().Where(x => x.GameIdGetter == GameId);