创建一个属性setter代表 [英] Creating a property setter delegate

查看:91
本文介绍了创建一个属性setter代表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建方式,一种是属性的lambda转换为委托:

I have created methods for converting a property lambda to a delegate:

public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
    var result = Expression.Lambda(propertyLambda.Body).Compile();
    return result;
}

public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
    var result = Expression.Lambda(propertyLambda.Body).Compile();
    return result;
}

这些工作:

Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();

Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();

但这些不会编译:

but these won't compile:

Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});

Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});

该MakeSetter线失败,出现类型参数不能从使用推断。尝试显式指定类型参数。

The MakeSetter lines fail with "The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly."

是我想要做的可能吗?先谢谢了。

Is what I'm trying to do possible? Thanks in advance.

推荐答案

防爆pression API支持这在.NET 4.0中,但可悲的是C#编译器没有按再增加任何额外的糖果支持。但好消息是,你可以平凡采取得到前pression(其中C#编译器的可以的写),并重新写为设置EX pression。

The Expression API supports this in .NET 4.0, but sadly the C# compiler doesn't add any extra candy to support. But the good news is that you can trivially take a "get" expression (which the C# compiler can write) and re-write it as a "set" expression.

和甚至更好;如果你没有.NET 4.0,还有的至少的执行设置通过写为搞定一个前pression的另外两种方式。

And even better; if you don't have .NET 4.0, there are still at least two other ways of performing a "set" via an expression written as a "get".

在这里,他们都是为信息:

Here they all are, for info:

using System;
using System.Linq.Expressions;
using System.Reflection;
class Foo {
    public string Bar { get; set; }
    static void Main() {
        // take a "get" from C#
        Expression<Func<Foo, string>> get = foo => foo.Bar;

        // re-write in .NET 4.0 as a "set"
        var member = (MemberExpression)get.Body;
        var param = Expression.Parameter(typeof(string), "value");
        var set = Expression.Lambda<Action<Foo, string>>(
            Expression.Assign(member, param), get.Parameters[0], param);

        // compile it
        var action = set.Compile();
        var inst = new Foo();
        action(inst, "abc");
        Console.WriteLine(inst.Bar); // show it working

        //==== reflection
        MethodInfo setMethod = ((PropertyInfo)member.Member).GetSetMethod();
        setMethod.Invoke(inst, new object[] { "def" });
        Console.WriteLine(inst.Bar); // show it working

        //==== Delegate.CreateDelegate
        action = (Action<Foo, string>)
            Delegate.CreateDelegate(typeof(Action<Foo, string>), setMethod);
        action(inst, "ghi");
        Console.WriteLine(inst.Bar); // show it working
    }
}

这篇关于创建一个属性setter代表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆