我有一个接受表达式类型参数的方法,在我的方法中我想获得这个表达式的值,但是找不到热点。
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
答案 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进行查询,那么使用表达式并不是真正的方法 - 创建单独的GetUserByEmail
和GetUser
方法将会除非你真的想在某个人用一个意外的表达式调用{{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)