Как получить значения выражения Linq - PullRequest
4 голосов
/ 23 декабря 2010

У меня есть метод, который принимает параметр типа 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 == email Я позвоню GetuserByEmail SP

Ответы [ 4 ]

3 голосов
/ 23 декабря 2010

Выражение может быть уменьшено до нескольких выражений.

 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 голос
/ 23 декабря 2010

Теоретически вы можете пройтись по дереву выражений в query.Body, чтобы определить назначение функции - в этом случае это будет BinaryExpression, в котором вам нужно будет проверить Left и Rightсвойства, чтобы увидеть, что сравнивается.

Тем не менее, я хотел бы предложить, что если вы используете конкретные SP для выполнения запросов, то использование выражения на самом деле не лучший способ - создание отдельных GetUserByUsername и *Методы 1008 * будут более устойчивыми, если вы действительно не хотите создавать исключения, когда кто-то вызывает GetUser с неожиданным выражением.

1 голос
/ 23 декабря 2010

Возможно, вам следует использовать LINQ для SQL.Он делает именно то, что вы хотите: разбить выражение и посмотреть, какие поля и сравнения вам нужны.Я не предлагаю делать это вручную, но если вы хотите, то посмотрите на члены класса Expression, это дерево выражений и будет иметь такие узлы, как доступ к свойствам и сравнение.

0 голосов
/ 23 декабря 2010

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)

...