为什么将表达式对象传递到 where returns 与键入 lambda 表达式的结果不同?
Why does passing an expression object to where returns a different result than typing the lambda expression?
我有以下代码 returns 正确地列出了六个对象
var items = db.items.take(100);
var result = items.Where(m => m.Cost.ToString().ToLower().Contains("67.5")).ToList(); //returns 6 items
我正在尝试使用动态表达式做同样的事情。
// Print out the expression.
// .ToString() returns "m => m.Cost.ToString().ToLower().Contains("67.5")"
var whereClause = ContainsPredicate<item>("Cost", "67.5");
var result = items.Where(whereClause).ToList(); //returns 0 items
当我尝试使用 sql 探查器查看发送到数据库的内容时,我注意到它删除了我的子句并添加了 WHERE 0 = 1
ContainsPredicate 方法实现:
public static Expression<Func<T, bool>> ContainsPredicate<T>(string memberName, string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var member = Expression.PropertyOrField(parameter, memberName);
MethodCallExpression memberToString = Expression.Call(Expression.Constant(member), member.GetType().GetMethod("ToString", Type.EmptyTypes));
MethodCallExpression memberToLower = Expression.Call(memberToString,"ToLower", null);
var body = Expression.Call(memberToLower,"Contains",Type.EmptyTypes,Expression.Constant(searchValue));
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
如有任何建议,我们将不胜感激。谢谢。
public static void Test()
{
var myItem = new Item() { Cost = 67.5 };
var items = new List<Item> { myItem };
var result = items.Where(m =>
m.Cost.ToString().ToLower().
Contains("67,5")).ToList();
var whereClause = ContainsPredicate<Item>("Cost", "67,5");
// var test1 = whereClause(myItem);
var result2 = items.Where(whereClause).ToList(); // returns 1 result in my case
}
public static Func<T, bool> ContainsPredicate<T>(string memberName, string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var member = Expression.PropertyOrField(parameter, memberName);
// Mistake was here:
var doubleToStr = member.Type.GetMethod("ToString", Type.EmptyTypes);
MethodCallExpression memberToString = Expression.Call(member, doubleToStr);
MethodCallExpression memberToLower =
Expression.Call(memberToString, "ToLower", null);
var body = Expression.Call(memberToLower, "Contains", Type.EmptyTypes
, Expression.Constant(searchValue));
var lamb = Expression.Lambda<Func<T, bool>>(body, parameter);
// we need to compile
return lamb.Compile();
}
我做的第一件事就是编译 memberToLower
并返回字符串 "m.cost" 而不是你的双精度字符串。 "m.cost" 显然永远不会包含“67.5”。就这样吧。
你确定你不想要这样的东西吗:
public static Func<T, bool> ContainsPredicate2<T>(string memberName, string searchValue)
{
var prop = typeof(T).GetProperty(memberName);
Func<T, bool> func = (T obj2) =>
prop.GetValue(obj2).ToString().ToLower().Contains(searchValue);
return func;
}
我有以下代码 returns 正确地列出了六个对象
var items = db.items.take(100);
var result = items.Where(m => m.Cost.ToString().ToLower().Contains("67.5")).ToList(); //returns 6 items
我正在尝试使用动态表达式做同样的事情。
// Print out the expression.
// .ToString() returns "m => m.Cost.ToString().ToLower().Contains("67.5")"
var whereClause = ContainsPredicate<item>("Cost", "67.5");
var result = items.Where(whereClause).ToList(); //returns 0 items
当我尝试使用 sql 探查器查看发送到数据库的内容时,我注意到它删除了我的子句并添加了 WHERE 0 = 1
ContainsPredicate 方法实现:
public static Expression<Func<T, bool>> ContainsPredicate<T>(string memberName, string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var member = Expression.PropertyOrField(parameter, memberName);
MethodCallExpression memberToString = Expression.Call(Expression.Constant(member), member.GetType().GetMethod("ToString", Type.EmptyTypes));
MethodCallExpression memberToLower = Expression.Call(memberToString,"ToLower", null);
var body = Expression.Call(memberToLower,"Contains",Type.EmptyTypes,Expression.Constant(searchValue));
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
如有任何建议,我们将不胜感激。谢谢。
public static void Test()
{
var myItem = new Item() { Cost = 67.5 };
var items = new List<Item> { myItem };
var result = items.Where(m =>
m.Cost.ToString().ToLower().
Contains("67,5")).ToList();
var whereClause = ContainsPredicate<Item>("Cost", "67,5");
// var test1 = whereClause(myItem);
var result2 = items.Where(whereClause).ToList(); // returns 1 result in my case
}
public static Func<T, bool> ContainsPredicate<T>(string memberName, string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var member = Expression.PropertyOrField(parameter, memberName);
// Mistake was here:
var doubleToStr = member.Type.GetMethod("ToString", Type.EmptyTypes);
MethodCallExpression memberToString = Expression.Call(member, doubleToStr);
MethodCallExpression memberToLower =
Expression.Call(memberToString, "ToLower", null);
var body = Expression.Call(memberToLower, "Contains", Type.EmptyTypes
, Expression.Constant(searchValue));
var lamb = Expression.Lambda<Func<T, bool>>(body, parameter);
// we need to compile
return lamb.Compile();
}
我做的第一件事就是编译 memberToLower
并返回字符串 "m.cost" 而不是你的双精度字符串。 "m.cost" 显然永远不会包含“67.5”。就这样吧。
你确定你不想要这样的东西吗:
public static Func<T, bool> ContainsPredicate2<T>(string memberName, string searchValue)
{
var prop = typeof(T).GetProperty(memberName);
Func<T, bool> func = (T obj2) =>
prop.GetValue(obj2).ToString().ToLower().Contains(searchValue);
return func;
}