如果我能够通过Lambda表达式(下面)分配
,这将非常简单//An expression tree cannot contain an assignment operator
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName = "Tim";
由于赋值运算符,上面的代码无效。我需要传递一个lambda表达式,以便识别需要设置的复杂对象中的属性。在某些情况下,复杂对象具有List,因此有重复的对象类型和名称,这就是为什么我需要lambda显式引用要更新的对象中的字段。
我可以使用以下方法检索值,没问题。但我不知道如何使用相同的逻辑来设置值,我遇到了Expression.Assign,并相信这可能是解决方案。
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName;
var result = FindByProperty(expression);
public static string FindByProperty(Expression<Func<Contract, object>> propertyRefExpr)
{
ComplexObj obj = new ComplexObj();
Contact myContact = new Contact();
myContact.FirstName = "Allen";
obj.Contacts = new List<Contact>{myContact};
return propertyRefExpr.Compile().Invoke(obj);
}
更新
“将属性赋值作为表达式树传递给方法......”
对ParentTypeA使用SetValue方法,Value将不起作用。 (下面的代码)
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName;
obj.AssignNewValue(expression, firstName);
public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value)
{
var propertyInfo = (PropertyInfo)((MemberExpression)expression.Body).Member;
propertyInfo.SetValue(obj, value, null);
}
答案 0 :(得分:13)
我最终使用了以下解决方案。干杯
ComplexObj obj = new ComplexObj();
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[index].FirstName;
obj.AssignNewValue(expression, firstName);
public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value)
{
ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object));
Expression targetExpression = expression.Body is UnaryExpression ? ((UnaryExpression)expression.Body).Operand : expression.Body;
var newValue = Expression.Parameter(expression.Body.Type);
var assign = Expression.Lambda<Action<ComplexObj, object>>
(
Expression.Assign(targetExpression, Expression.Convert(valueParameterExpression, targetExpression.Type)),
expression.Parameters.Single(),
valueParameterExpression
);
assign.Compile().Invoke(obj, value);
}
答案 1 :(得分:0)
链接问题可能是“正确”的答案,但只是为了完整起见,你可以做更多这样的事情......它确实遵循“告诉,不要”请问“方法有点好,虽然我不能说我喜欢实施......
void Main()
{
Expression<Func<ComplexObj, object>> expression =
obj => obj.Contacts[0].SetFirstName("Tim");
}
public class ComplexObj
{
public ComplexObj() { Contacts = new List<SimpleObj>(); }
public List<SimpleObj> Contacts {get; private set;}
}
public class SimpleObj
{
public string FirstName {get; private set;}
public SimpleObj SetFirstName(string name) { this.FirstName = name; return this; }
}