在表达式树中分配实例成员字段
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 中的相同。
我尝试通过将 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 中的相同。