如何获取Linq表达式的值

6

我有一个方法,它接受Expression类型的参数,在我的方法中,我想获取这个表达式的值,但是不知道如何做到。

private User GetUser(Expression<Func<User, bool>> query)
{
  User user = Context.User.Where(query).FirstOrDefault();
  return user;
}

我正在使用不同的参数调用此方法,例如

GetUser(u => u.Username == username);

GetUser(u=> u.Email == email);

我希望将GetUser方法改为使用存储过程,但需要找到查询参数中的内容。

我想检查查询是否为u.Username == username 我将调用GetUserByUsername存储过程。 如果查询是u.Email == email 我将调用GetuserByEmail存储过程。

4个回答

7
表达式可以简化为几个表达式。
 var body = query.Body as BinaryExpression;
 if (body != null)
 {
    var left = body.Left as MemberExpression;
    if (left != null)
    {
        Console.WriteLine(left.Member.Name);   
         // You can get "Username" or "Email" here
    }
 }

顺便说一下,我认为你走错了方向。想象一下这种情况:其他开发人员看到你的GetUser方法,并以这种方式使用它:

var result = GetUser(u => u.Email.Equals("abc@foo.com")); //or
var another = GetUser(u => u.Username.Contains("bar"));

他可能认为他是正确的,但实际上你的方法并不能给他理想的结果!你可以说“没关系,我会通知他们这个改变”,但是在你离开这个团队/公司后的日子里呢?如果一种方法不像它的声明那样表现,那将是一场噩梦。

也许还要检查运算符是否相等。我不记得如何做了,但我知道它可以(而且可能应该)完成。 - Davy8

1
也许你应该使用LINQ for SQL。它可以完全满足你的需求:分解表达式并查看所需的字段和比较。我不建议手动执行此操作,但如果你想这样做,那么请查看Expression类的成员,它是一个表达式树,将具有诸如属性访问和比较之类的节点。

1

你理论上可以遍历 query.Body 中的表达式树,以确定函数的意图 - 在这种情况下,它将是一个 BinaryExpression ,其中您需要检查 LeftRight 属性以查看正在比较什么。

但是,如果您使用特定的 SP 来进行查询,则建议不要使用表达式 - 创建单独的 GetUserByUsernameGetUserByEmail 方法将更加健壮,除非您真的希望在某人调用具有意外表达式的 GetUser 时抛出异常。


0

Where 接受 Func<TSource, bool> 谓词,而不是 Expression。请检查以下示例:

class Program
{
    private static List<int> l = new List<int> { 1, 2, 3, 4, 5 };

    static void Main(string[] args)
    {
        Console.WriteLine(GetNum(x => x > 3));
        Console.ReadKey();
    }

    private static int GetNum(Func<int, bool> predicate)
    {
        return l.Where(predicate).FirstOrDefault();
    }
}

它返回4。因此,请更改您的函数定义为private User GetUser(Func<User,bool> query)


1
我认为这不是OP所寻找的。如果您读完问题的结尾,Yucel想根据正在检查的参数调用不同的存储过程。 - Davy8
“Where” 接受一个 “Expression”。 - ta.speot.is

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接