属性获取/设置运行时反射类的代理

时间:2010-09-08 22:28:27

标签: c# delegates properties

据我所知,Delegates提供的高性能反射可能比常规显式c#代码慢15%。但是,我在stackoverflow上找到的所有示例都是基于通过委托访问的方法/属性类型的先验知识。

鉴于此类的先验知识,为什么首先要反映代表访问?

无论如何,我面临的反射编码任务是如何为未知的类属性列表实现高性能属性获取/设置访问,其中只在运行时提供类类型名称?我可以编写反射检查的基础知识来生成属性列表,但是如何为一组可能随机的属性类型连接一组基于委托的访问器?

假设属性类型仅限于一系列基本数据库列类型,则返回一个case语句:

Func<int> or Func<string> etc? 

编辑-1:我仅限于.Net 3.5

1 个答案:

答案 0 :(得分:4)

此解决方案使用表达式树,因为它们相当容易编写,并且它们提供了方便的Compile()方法来获取可以调用的实际Delegate。我让Func实际上接受了对象(所以Func&lt; T,TResult&gt;而不仅仅是Func&lt; TResult&gt;)所以你可以从任何实例获取属性值。

修改:添加了setter实现。

public class MyClass
{
    public string MyStringProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        PropertyInfo propertyInfo = typeof(MyClass).GetProperty("MyStringProperty");
        Delegate getter = CreateGetter(propertyInfo);
        Delegate setter = CreateSetter(propertyInfo);
        object myClass = new MyClass();
        setter.DynamicInvoke(myClass, "Hello");
        Console.WriteLine(getter.DynamicInvoke(myClass));
    }

    public static Delegate CreateGetter(PropertyInfo property)
    {
        var objParm = Expression.Parameter(property.DeclaringType, "o");
        Type delegateType = typeof(Func<,>).MakeGenericType(property.DeclaringType, property.PropertyType);
        var lambda = Expression.Lambda(delegateType, Expression.Property(objParm, property.Name), objParm);
        return lambda.Compile();
    }

    public static Delegate CreateSetter(PropertyInfo property)
    {
        var objParm = Expression.Parameter(property.DeclaringType, "o");
        var valueParm = Expression.Parameter(property.PropertyType, "value");
        Type delegateType = typeof(Action<,>).MakeGenericType(property.DeclaringType, property.PropertyType);
        var lambda = Expression.Lambda(delegateType, Expression.Assign(Expression.Property(objParm, property.Name), valueParm), objParm, valueParm);
        return lambda.Compile();
    }
}

首先使用动态setter将其设置为“Hello”,然后使用动态getter从对象中获取属性,从而打印出“Hello”。