如何获取Expression <Func <object >>目标对象设置值?

gga*_*bor 2 c# lambda expression func

我尝试创建一个比较原始值和更新后的值的函数,并将原始值设置为更新后的值(如果不同)。该函数的作用更多,因此我简化了对主题的讨论:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我想这样打电话:

manager.Match<TestClass>(() => original.TestProperty, () => updated.TestProperty);
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 5

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果此类型是值类型,那么您将通过调用此表达式创建的内容是该值的副本,并且您最终将对该副本进行变异,但是只要它是引用类型,您就可以复制参考,实际对象实际上将被突变。

您可以采取另一种完全不同的途径。您可以简单地创建一个表示将必须的值分配给该表达式的表达式,而不是尝试评估可以将此属性分配给的变量。如果从值类型访问属性,则该代码甚至将起作用,因为它实际上是对变量进行突变,而不是获取该变量的值并对其进行突变。

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管使方法通用,您实际上也没有将通用参数用作两个函数的结果类型。