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

标签 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);
    }
}

我想这样打电话:

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/

相关文章:

c# - 需要 n 层架构反馈

c# - 执行 IEnumerable 方法

c# - 这个 Lambda 表达式有什么问题?

sql - 字符串是否可以由一组字母组成的正则表达式

javascript - 如何在mapbox GL JS上按日期范围过滤数据?

c# - 在 C# 中使用正则表达式查找文本中的单词

c# - 如何在 C# struct 中声明和使用固定大小的 char 缓冲区

c# - 使用 Enterprise Library 5 进行数据库记录

c# - 可以替代面向对象设计模式的功能或动态技术示例

java - 为什么 C 和 Java 的表达式 m++ + (++m) 的输出不同