#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);
}