我正在尝试构造一个表达式树来对字符串数组进行操作。我需要弄清楚如何使用Equal方法。
有谁可以给我一个例子 1)使用Expression.Equal(或.Equals)方法将字符串与常量进行比较,并使用 2)使用任何排序的表达式来使用string.Contains()方法进行过滤。
我正在尝试学习表达式树的机制,但到目前为止,我还没有找到一个好的教程。非常感谢你的帮助。
string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();
// what should go below here?
ParameterExpression p1 = Expression.Parameter(typeof(string), "c");
Expression left = Expression.Constant("s2");
Expression e1 = Expression.Equal(left, p1);
IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);
答案 0 :(得分:3)
Aaah,我明白你在问什么...而且你真的进入了一些非常模糊的水域,这是.NET反射库不适合使用的少数几个领域之一。您必须创建一个调用表达式来调用queryableData对象上的Queryable.Where(),并使用该表达式创建一个新查询...问题是在.NET中获取方法的泛型版本不一定是最简单的你生活中遇到过的事情:
MethodCallExpression call = Expression.Call(
null, // Calling Queryable.Where(), extension method, not instance method
getGenericMethod<string>(typeof(Queryable), "Where", typeof(IQueryable<string>), typeof(Expression<Func<string,bool>>)),
Expression.Constant(queryableData),
Expression.Lamda(
e1,
p1)
);
IQueryable<string> res = queryableData.Provider.CreateQuery<string>(call);
您还必须定义getGenericMethod(您可以在其他地方找到更好的在线实现,这是一个非常简单的方法):
private static MethodInfo getGenericMethod<T>(Type type, string name, params Type[] paramTypes)
{
MethodInfo[] methods = type.GetMethods(name);
foreach(MethodInfo mi in methods)
{
if(!mi.IsGenericMethodDefinition) // or some similar property
continue;
if(mi.GetGenericArguments().Length != 1)
continue;
if(mi.GetParameters().Length != paramTypes.Length)
continue;
MethodInfo genMethod = mi.MakeGenericMethod(new Type[]{typeof(T)});
var ps = genMethod.GetParameters();
bool isGood = true;
for(int i = 0; i < ps.Length; i++)
{
if(ps[i].ParameterType != paramTypes[i])
{
isGood = false;
break;
}
}
if(isGood)
return genMethod;
}
return null;
}
那里几乎无疑有一些错误,但我希望你能从那里看到去哪里......
答案 1 :(得分:0)
只是提出我的解决方案:
string[] arr = {"s1","s2","s3"};
IQueryable<String> queryableData = arr.AsQueryable<string>();
ParameterExpression pe = Expression.Parameter(typeof(string), "company");
Expression right = Expression.Constant("on");
Expression left = Expression.Call(pe, typeof(string).GetMethod("Contains"), right);
MethodCallExpression e2 = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { queryableData.ElementType },
queryableData.Expression,
Expression.Lambda<Func<string, bool>>(left, new ParameterExpression[] { pe }));
IQueryable<string> res = queryableData.Provider.CreateQuery<string>(e2);