为什么将表达式对象传递到哪里比输入lambda表达式返回不同的结果?

问题描述 投票:2回答:1

我有以下代码可以正确返回六个对象的列表

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 profiler来查看发送到数据库的内容时,我注意到它删除了我的子句并添加了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);
        }

任何建议都值得赞赏。谢谢。

c# .net linq lambda expression-trees
1个回答
0
投票
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”而不是您的double。 “ 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.