c# - 创建属性 setter 委托(delegate)

标签 c# properties lambda delegates

我已经创建了将属性 lambda 转换为委托(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();

但是这些不会编译:

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

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

MakeSetter 行失败,显示“无法从用法中推断类型参数。尝试明确指定类型参数。”

我想做的事情可行吗?提前致谢。

最佳答案

Expression API 在 .NET 4.0 中支持这一点,但遗憾的是 C# 编译器没有添加任何额外的支持。但好消息是,您可以轻松获取“get”表达式(C# 编译器可以编写)并将其重写为“set”表达式。

甚至更好;如果您没有 .NET 4.0,至少还有两种其他方法可以通过写为“get”的表达式执行“set”。

它们都在这里,以供引用:

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

关于c# - 创建属性 setter 委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2823236/

相关文章:

c# - 如何删除重复的电子邮件地址

c# - 未初始化的浮点变量,重新定义不确定的行为

javascript - 在没有 arrayToDataTable() 的情况下修改 Google Column Chart 中的列颜色

python - 从 lambda 连接到 Redshift 并使用 python 获取一些记录

c# - linq lambda Orderby 的 SQL 语句

c# - 关于 lambda 表达式的专家意见 - ViewModels

c# - Image.GetThumbnailImage 方法和质量

c# - 在 Visual C# 中匹配字符串中的字符

c# - 指向未访问 set 关键字的属性的构造函数

java - 在哪里存储一致的应用程序属性?