Лучшие практики создания универсальных методов-делегатов и доступа аксессоры


Я хочу создать делегат для доступа к свойствам различных объектов, не зная их заранее.

У меня есть следующие определения

public delegate T MyMethod<K, T>(K data);

public static MyMethod<K, T> CreatePropertyGetter<K, T>(PropertyInfo property)
{       
   MethodInfo mi = property.DeclaringType.GetMethod("get_" + property.Name);        
   return (MyMethod<K, T>)Delegate.CreateDelegate(typeof(MyMethod<K, T>), mi);
}

где T может быть десятичное число, строка, дата или инт

У меня есть некоторые инициализационный код, что позволит создать метод mymethod делегатов, на основе отраженных свойств объекта следующим образом:

foreach (PropertyInfo property in entityType.GetProperties())
{               
    switch (property.PropertyType.Name)
    {
        case "System.Decimal":
            return CreatePropertyGetter<T, decimal>(property);
        case "System.DateTime":
            return CreatePropertyGetter<T, DateTime>(property);
        case "System.String":
            return CreatePropertyGetter<T, DateTime>(property);
    }
}

Есть ли лучший способ

  1. создавать аксессоры?
  2. перечислять поддерживаемые жестко видах имущества как строки?

Однако, производительность является важным фактором, так как эти делегаты будут называться чаще (тикающий сценарий), так что любое литье будет замедлять его. В то время как более изящное решение желательно, производительность по-прежнему моя главная забота



2533
6
задан 7 марта 2011 в 06:03 Источник Поделиться
Комментарии
2 ответа

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

Когда вы не уверены в том, что только требуемые виды являются те, которые указаны, или что новые типы очень часто, вы можете все еще использовать ваш текущий подход. Однако я хотел применить некоторые изменения:


  1. Использовать PropertyInfo.GetGetMethod() чтобы получить methodinfo для метода GET.

  2. Используйте тип PropertyType напрямую, чтобы определить, какие CreatePropertyGetter называть вместо имени типа.

  3. Использовать Функ вместо метода mymethod.

  4. Использовать словарь держа анонимные функции, которые создают правильный делегат для указанного типа ключа. Это может заменить оператора switch.

Последнюю точку можно следующим образом:

Dictionary<Type, Func<PropertyInfo, object>> getterCreators =
new Dictionary<Type, Func<PropertyInfo, object>>
{
{ typeof(string), p => CreatePropertyGetter<T, string>(p) },
{ typeof(DateTime), p => CreatePropertyGetter<T, DateTime>(p) },
{ typeof(decimal), p => CreatePropertyGetter<T, decimal>(p) }
};

Конечно, вам все равно придется бросить от объекта к нужному типу.

Обновление:

Как Timwi, указал в комментариях, п => CreatePropertyGetter(п) может быть снижен до: CreatePropertyGetter.

7
ответ дан 7 марта 2011 в 07:03 Источник Поделиться

Одно из предложений-создать тип -> тип карты всех типов, которые вы хотите поддерживать вместо того, чтобы оператор switch со строками.

0
ответ дан 7 марта 2011 в 07:03 Источник Поделиться