Динамическая функция выбора свойств lambda

#c# #properties #expression

#c# #свойства #выражение

Вопрос:

Я пытаюсь создать выражение выбора свойств с указанным типом и именем свойства. т.е. t => t.propertyName.

Следующий код компилируется просто отлично, но приводит к пустому значению. Может кто-нибудь, пожалуйста, указать на ошибку в коде?

     public static Expression<Func<T,object>> CreatePropSelectorExpression(string propName) where T:class,new()
    {
    var temp = Activator.CreateInstance<T>();
    ParameterExpression t = Expression.Parameter(typeof(T),"t");
    MemberExpression member = Expression.PropertyOrField(Expression.Constant(temp),propName);
    return Expression.Lambda<Func<T,object>>(member,t);
    }
  

Заранее спасибо

Комментарии:

1. Не беспокойтесь. Уже найдено решение. Необходимо использовать выражение-член вместо временной переменной

Ответ №1:

На самом деле вам не нужно создавать экземпляр вашего объекта T , вы просто создаете некоторые деревья выражений. На самом деле все сводится к следующему:

 Expression<Func<T, object>> CreatePropSelectorExpression<T>(string propertyName)
{
    var parameter = Expression.Parameter(typeof(T));
    var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(object));
    return Expression.Lambda<Func<T, object>>(body, parameter);
}
  

Комментарии:

1. какова цель выражения. Преобразовать()? Похоже, что она работает только с: var body = Expression. PropertyOrField(параметр, propertyName);

2. Метод convert гарантирует, что выражение имеет определенный тип. В конечном итоге это сводится к приведению. Это потребуется, если типом свойства является a ValueType , поскольку это превратится в операцию упаковки. Хотя при построении выражений лучше всего генерировать выражения ожидаемого типа, когда это возможно.

3. Хорошо, но не могли бы вы предоставить вложенный селектор с IEnumerable<string> propertyNames в качестве аргументов

Ответ №2:

Вложенная версия

 static Expression<Func<R, O>> 
CreatePropSelectorExpression<R,O>(IEnumerable<string> propertyName)
{
    ParameterExpression parameter = Expression.Parameter(typeof(R));
    Expression selector = propertyName
         .Aggregate((Expression)parameter, 
               (a, name) => Expression.PropertyOrField(a, name));
    return Expression.Lambda<Func<R,O>>(selector, parameter);
}