我怎样才能使这项工作具有深层属性

发布于 2024-09-01 21:33:28 字数 1760 浏览 1 评论 0原文

给出以下代码...

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

任何人都可以帮我修改它,以便我可以为深层属性和浅层属性创建 setValueExpression 吗?

谢谢。

Given the following code...

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; }

}

The call to DoLambdaStuff(foo, f => f.Name) works ok because I am accessing a shallow property, however the call to DoLambdaStuff(foo, f => f.Bar.Description) fails - although the creation of the getValue function works fine, the creation of the setValueExpression fails because I am attempting to access a deep property of the object.

Can anybody please help me to modify this so that I can create the setValueExpression for deep properties as well as shallow?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉城メ夜风 2024-09-08 21:33:28

您需要利用这样一个事实:您的 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);
    }

You need to take advantage of the fact that your expression.Body is already representing the property you want to set. This means you can use expression.Body as the left-hand-side in your assignment expression:

    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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文