在表达式树中分配实例成员字段

Assign instance member field in expression-trees

我尝试通过将 class 实例作为参数来修改 this answer。主要思想是为 class 成员创建一个 setter,无论它是字段还是 属性。我在属性方面很成功,但在字段方面遇到了困难。这是原代码的相关部分:

 public static Action<T> ToSetter<T>(Expression<Func<T>> expr) {
    var memberExpression = (MemberExpression)expr.Body;
    var instanceExpression = memberExpression.Expression;
    var parameter = Expression.Parameter(typeof(T));

    // assuming memberExpression.Member is FieldInfo;
    return Expression.Lambda<Action<T>>(Expression.Assign(memberExpression, parameter), parameter).Compile();        
}

申请:

 var setter= ToSetter<string>(() => myClient.WorkPhone);
 setter("12345");

这就是我想要的:

 public static Action<O,T> ToSetter<T,O>(Expression<Func<O,T>> expr) where O : class {
    var memberExpression = (MemberExpression)expr.Body;
    var instance = Expression.Parameter(typeof(O));
    var parameter = Expression.Parameter(typeof(T));

    // the following throws an InvalidOperationException exception:
    return Expression.Lambda<Action<O,T>>(
        Expression.Assign(memberExpression, parameter), parameter).Compile(); 
}

申请:

var setter= ToSetter<Client,string>(c=> c.WorkPhone);
setter(myClient, "12345");

我如何修改 Expression.Lambda<Action<O,T>>(Expression.Assign(memberExpression, parameter),instance, parameter).Compile() 以考虑 class O 的实例?

试试这个:

    // Example usage: ToSetter<MyEntity, string>(c => c.FirstName)
    public static Action<TEntity, TResult> ToSetter<TEntity, TResult>(Expression<Func<TEntity, TResult>> expr)
    {
        // This will be `c.FirstName`
        var memberExpression = (MemberExpression)expr.Body;
        // This will be `c`
        var instanceParameter = (ParameterExpression)memberExpression.Expression;
        // New parameter for passing value named `value`
        var valueParameter = Expression.Parameter(typeof(TResult), "value");

        // Construct `(c, value) => c.FirstName = value`
        return Expression.Lambda<Action<TEntity, TResult>>(
            Expression.Assign(memberExpression, valueParameter), // c.FirstName = value
            instanceParameter, // c
            valueParameter // value
        ).Compile();        
    }

您缺少的是 Lambda 调用的第二个参数。此外,memberExpression 有一些来自原始 lambda 的参数,它必须与新 lambda 中的相同。