如何获取Linq Expression的值

时间:2010-12-23 14:31:23

标签: c# linq 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 SP 如果查询是u.Email ==电子邮件 我将调用GetuserByEmail SP

4 个答案:

答案 0 :(得分:3)

表达式可以简化为几种表达式。

 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"));

他会认为他是正确的,但实际上你的方法不会给出他理想的结果!那么你可以说“没关系,我会告诉他们这个改变”,但是你退出这个团队/公司后的日子呢?如果某个方法的行为与其声明不同,那就太噩梦了。

答案 1 :(得分:1)

也许您应该使用LINQ for SQL。它完全符合您的要求:撕开表达并查看您需要的字段和比较。我不建议手动执行此操作,但如果您愿意,请查看Expression类的成员,它是一个表达式树,并且将具有属性访问和比较等节点。

答案 2 :(得分:1)

理论上,您可以在query.Body中遍历表达式树以确定函数的意图 - 在这种情况下,它将是BinaryExpression,您需要在Left中检查Right }}和GetUserByUsername属性可以查看正在比较的内容。

但是,我建议如果您使用特定的SP进行查询,那么使用表达式并不是真正的方法 - 创建单独的GetUserByEmailGetUser方法将会除非你真的想在某个人用一个意外的表达式调用{{1}}时抛出异常,否则会更加健壮。

答案 3 :(得分: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)