我尝试创建一个函数来比较原始值和更新值,并在不同时将原始值设置为更新值。该函数可以做更多的事情,所以我简化了以专注于主题:
public void Match<T>(Expression<Func<object>> original, Expression<Func<object>> updated)
{
var mex = original.Body as MemberExpression;
var funcOriginal = original.Compile();
var funcUpdated = updated.Compile();
var valueOriginal = funcOriginal();
var valueUpdated = funcUpdated();
if (valueOriginal != valueUpdated)
{
var info = mex.Member as PropertyInfo;
var target = ???; //How to get the original.TestProperty here?
info.SetValue(target, valueUpdated);
}
}
我想这样打电话:
manager.Match<TestClass>(() => original.TestProperty, () => updated.TestProperty);
最佳答案
成员信息的Expression
属性是从中获取属性的变量的表示。您只需调用它即可将其计算为一个值。
public static void Match<T>(Expression<Func<T>> original,
Expression<Func<T>> updated)
{
var mex = original.Body as MemberExpression;
var valueOriginal = original.Compile()();
var valueUpdated = updated.Compile()();
if (!object.Equals(valueOriginal, valueUpdated))
{
var info = mex.Member as PropertyInfo;
var target = Expression.Lambda(mex.Expression).Compile().DynamicInvoke();
info.SetValue(target, valueUpdated);
}
}
当然,如果此类型是值类型,那么您将通过调用此表达式创建的是该值的副本,并且最终会改变该副本,但只要它是引用类型,您就可以'将复制引用,并且实际对象实际上将被改变。
您还可以采取另一种完全不同的途径。您可以简单地创建一个表达式来表示将您拥有的值分配给该表达式,而不是尝试计算可以分配此属性的变量。如果从值类型访问属性,此代码甚至可以工作,因为它实际上是改变变量,而不是获取该变量的值并改变它。
public static void Match<T>(Expression<Func<T>> original,
Expression<Func<T>> updated)
{
var mex = original.Body as MemberExpression;
var valueOriginal = original.Compile()();
var valueUpdated = updated.Compile()();
if (!object.Equals(valueOriginal, valueUpdated))
{
var body = Expression.Assign(
Expression.MakeMemberAccess(mex.Expression, mex.Member),
updated.Body);
Expression.Lambda<Action>(body).Compile().Invoke();
}
}
尽管使方法通用,但您实际上也没有使用通用参数作为两个函数结果的类型。
关于c# - 如何获取Expression<Func<object>>目标对象来设置值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24206333/