运行时反射类的属性获取/设置委托

cam*_*ase 2 c# delegates properties

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

鉴于类的这种先验知识,为什么首先要诉诸反射的委托访问?

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

假设属性类型仅限于一系列基本的 DB 列类型,则返回一个 case 语句的答案是:

Func<int> or Func<string> etc? 
Run Code Online (Sandbox Code Playgroud)

编辑 1:我仅限于 .Net 3.5

Kir*_*oll 5

该解决方案使用表达式树,因为它们相当容易组合,并且它们提供了方便的 Compile() 方法来获取您可以调用的实际委托。我让 Func 实际上接受了对象(因此 Func<T, TResult> 而不仅仅是 Func<TResult>),因此您可以从任何实例获取属性值。

编辑:还添加了 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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