Свойство get / set Делегаты для времени выполнения отраженного класса - PullRequest
1 голос
/ 09 сентября 2010

Я понимаю, что делегаты предлагают высокую производительность отражения, может быть, только на 15% медленнее, чем обычный явный код C #.Однако все примеры, которые я могу найти в stackoverflow, основаны на предварительном знании типа метода / свойства, доступ к которому осуществляется через делегата.

Учитывая такое предварительное знание класса, зачем прибегать к отраженному делегированному доступу впервое место?

В любом случае, задача кодирования отражения, с которой я сталкиваюсь, заключается в том, как реализовать высокопроизводительный доступ к свойствам для получения / установки неизвестного списка свойств класса, где только имя типа класса предоставляется во время выполнения?Я могу кодировать основы проверки отражения, чтобы получить список свойств, но как мне подключить набор аксессоров на основе делегатов для потенциально случайного набора типов свойств?

Предполагая, что типы свойств ограничены диапазономиз базовых типов столбцов БД является ответом на заявление case, которое возвращает:

Func<int> or Func<string> etc? 

Edit-1: я ограничен .Net 3.5

1 Ответ

4 голосов
/ 09 сентября 2010

Это решение использует деревья выражений, поскольку их довольно легко составлять, и они предоставляют удобный метод Compile () для получения фактического Делегата, к которому вы можете обращаться.Я сделал Func на самом деле взять объект (так что Funcа не просто Func ), поэтому вы можете получить значение свойства из любого экземпляра.

Редактировать : также добавлена ​​реализация установки.

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

Распечатывает «Hello», сначала используя динамический установщик, чтобы установить его в «Hello», а затем используядинамический геттер для получения свойства от объекта.

...