C# 如何从表达式树设置属性值?

C# 如何从表达式树设置属性值?,c#,.net,expression-trees,C#,.net,Expression Trees,我想设置表达式树中引用的属性值 using System; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; namespace ConsoleApp8 { class TestObject { public double X { get; set; } } class Program { static Ac

我想设置表达式树中引用的属性值

using System;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleApp8
{
    class TestObject
    {
        public double X { get; set; }
    }

    class Program
    {
        static Action<double> GetSetterForX(Expression<Func<double>> expression)
        {
            var body = expression.Body;
            var operand = body as MemberExpression;
            var propertyInfo = (PropertyInfo) (operand.Member);
            var setter = propertyInfo.GetSetMethod(true);

            // At this point I have the setter. But how do I get access to the testObject?

            return null;
        }

        static void Main(string[] args)
        {
            var testObject = new TestObject();
            var setter = GetSetterForX(() => testObject.X);
            setter.Invoke(5);
            Debug.Assert(testObject.X == 5);
        }
    }
}
使用系统;
使用系统诊断;
使用System.Linq.Expressions;
运用系统反思;
名称空间控制台App8
{
类TestObject
{
公共双X{get;set;}
}
班级计划
{
静态操作GetSetterForX(表达式)
{
var body=expression.body;
变量操作数=作为MemberExpression的主体;
var propertyInfo=(propertyInfo)(操作数.Member);
var setter=propertyInfo.GetSetMethod(true);
//现在我有了setter,但是如何访问testObject呢?
返回null;
}
静态void Main(字符串[]参数)
{
var testObject=新的testObject();
var setter=GetSetterForX(()=>testObject.X);
setter.Invoke(5);
Assert(testObject.X==5);
}
}
}
我可以获得setter,但找不到访问实例(testObject)的方法。有办法吗

请注意,这是一个简化的示例。我将使用更复杂的表达式,其中包含许多属性引用,并且我希望能够(单独)设置所有这些属性引用

更新

澄清。我希望返回一个setter,它只接受一个double,并分配testObject的X属性。这应该是可能的,而不需要在setter中显式传递对testObject的引用。 我也可以做同样的事情来得到一个能手,但不能得到二传手。下面是getter代码:

static Func<double> GetGetterForX(Expression<Func<double>> expression)
{
    var body = expression.Body;
    var operand = body as MemberExpression;
    var result = new Func<double>(() => (double) GetValue(operand));

    return result;
}

private static object GetValue(MemberExpression member)
{
    var objectMember = Expression.Convert(member, typeof(object));
    var getterLambda = Expression.Lambda<Func<object>>(objectMember);
    var getter = getterLambda.Compile();
    return getter();
}
static Func getterforx(表达式)
{
var body=expression.body;
变量操作数=作为MemberExpression的主体;
var result=newfunc(()=>(双精度)GetValue(操作数));
返回结果;
}
私有静态对象GetValue(MemberExpression成员)
{
var objectMember=Expression.Convert(成员,typeof(对象));
var getterLambda=Expression.Lambda(objectMember);
var getter=getterLambda.Compile();
返回getter();
}

返回的getter始终处理testObject实例。无需再次传入testObject。

您需要返回
MethodInfo
而不是
Action
,同时
调用(object obj,object[]params)
获取原始对象和参数:

static MethodInfo GetSetterForX(表达式)
{
var body=expression.body;
变量操作数=作为MemberExpression的主体;
var propertyInfo=(propertyInfo)(操作数.Member);
var setter=propertyInfo.GetSetMethod(true);
回程设定器;
}
公共静态void Main()
{
var testObject=新的testObject();
var setter=GetSetterForX(()=>testObject.X);
Invoke(testObject,新对象[]{5});
Assert(testObject.X==5);
}

Fiddle:

只要输入lambda表达式表示成员访问器,就可以使用传递输入lambda表达式体和表示值的参数,例如

static Action<double> GetSetterForX(Expression<Func<double>> expression)
{
    var parameter = Expression.Parameter(typeof(double), "value");
    var body = Expression.Assign(expression.Body, parameter);
    var lambda = Expression.Lambda<Action<double>>(body, parameter);
    return lambda.Compile();
}
静态操作GetSetterForX(表达式) { var参数=表达式参数(typeof(double),“value”); var body=Expression.Assign(Expression.body,参数); var lambda=表达式.lambda(主体,参数); 返回lambda.Compile(); }
这不是我想要的。我希望能够通过提供
()=>testobject.X
表达式,从testobject获得X的值。我相信这应该是可能的,我可以写一个getter。我会更新这个问题