【问题标题】:How can I make this work with deep properties我怎样才能使这项工作与深层属性
【发布时间】:2010-05-16 18:53:38
【问题描述】:

给定以下代码...

class Program {

    static void Main(string[] args) {

        Foo foo = new Foo { Bar = new Bar { Description= "Martin" }, Name = "Martin" };

        DoLambdaStuff(foo, f => f.Name);
        DoLambdaStuff(foo, f => f.Bar.Description);

    }

    static void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression) {

        // Set up and test "getter"...

        Func<TObject, TValue> getValue = expression.Compile();

        TValue stuff = getValue(obj);

        // Set up and test "setter"...

        ParameterExpression objectParameterExpression = Expression.Parameter(typeof(TObject)), valueParameterExpression = Expression.Parameter(typeof(TValue));
        Expression<Action<TObject, TValue>> setValueExpression = Expression.Lambda<Action<TObject, TValue>>(
            Expression.Block(
                Expression.Assign(Expression.Property(objectParameterExpression, ((MemberExpression)expression.Body).Member.Name), valueParameterExpression)
            ), objectParameterExpression, valueParameterExpression
        );
        Action<TObject, TValue> setValue = setValueExpression.Compile();


        setValue(obj, stuff);

    }

}

class Foo {

    public Bar Bar { get; set; }
    public string Name { get; set; }

}

class Bar {

    public string Description{ get; set; }

}

DoLambdaStuff(foo, f =&gt; f.Name) 的调用工作正常,因为我正在访问浅层属性,但是对DoLambdaStuff(foo, f =&gt; f.Bar.Description) 的调用失败 - 尽管getValue 函数的创建工作正常,setValueExpression 的创建失败,因为我我正在尝试访问对象的深层属性。

谁能帮我修改这个,以便我可以为深层和浅层属性创建setValueExpression

谢谢。

【问题讨论】:

    标签: .net lambda


    【解决方案1】:

    您需要利用您的 expression.Body 已经代表您要设置的属性这一事实。这意味着您可以在赋值表达式中使用 expression.Body 作为左侧:

        public static void Main(string[] args)
        {
            Foo foo = new Foo { Bar = new Bar { Name = "Martin", Buzz = new Fiz() { Name = "Carl" }}, Name = "Martin" };
    
            DoLambdaStuff(foo, f => f.Bar.Name, "Dennis");
            DoLambdaStuff(foo, f => f.Bar.Buzz.Name, "Dennis");
            Console.WriteLine(foo.Bar.Name);
            Console.WriteLine(foo.Bar.Buzz.Name);
    
        }
        static void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression, TValue valueToSet)
        {
            // Getter.
            Func<TObject, TValue> getter = expression.Compile();
            TValue stuff = getter(obj);
    
            ParameterExpression pObj = expression.Parameters[0];
            ParameterExpression pValue = Expression.Parameter(typeof (TValue), "value");
            var setterBlock = Expression.Block(
                Expression.Assign(expression.Body, pValue)
                );
    
            var setterExpression = Expression.Lambda<Action<TObject, TValue>>(setterBlock, pObj, pValue);
            Action<TObject, TValue> setter = setterExpression.Compile();
    
            // Test 
            setter(obj,valueToSet);
        }
    

    【讨论】:

    • 谢谢,这似乎正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    相关资源
    最近更新 更多