Могу ли я принять тип делегата T и выражение <T>в одном и том же параметре? - PullRequest
3 голосов
/ 31 августа 2010

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

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

public IEnumerable<IFieldInfo<SomeType>> Fields {
  get {
    yield return FieldHelper.GetFieldInfo<SomeType>(t => t.SomeField);
    yield return FieldHelper.GetFieldInfo<SomeType>(t => t.SomeOtherField);
  }
}

Скажем, что интерфейс IFieldInfo выглядит примерно так:

interface IFieldInfo<in T> {
  public string PropertyName {get;}
  public object GetValue(T obj);
}

В контексте моего приложения, Fields свойство будет доступно довольно часто;метод GetValue() будет вызываться довольно часто, но к PropertyName (и другим полям метаданных / отражений, которые я пропустил для ясности) будет обращаться реже.Есть много мест, где необходимо реализовать свойство Fields, и иногда много полей, поэтому для ясности и поддержки кода важно, чтобы код, который вызывает GetFieldInfo, был простым и понятным;дублирование списка полей или дублирование параметра будет просто с запросом об ошибках, когда они не синхронизируются.

Итак, как мне написать GetFieldInfo?Если я сделаю:

public static IFieldInfo<T> GetFieldInfo<T>(Func<T, object> getter);

, тогда я могу реализовать GetValue() тривиально, вызвав getter(obj), но у меня нет возможности получить доступ к имени.

Если, с другой стороны, яdo:

public static IFieldInfo<T> GetFieldInfo<T>(Expression<Func<T, object>> getter)

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

Есть ли способ написать мой GetFieldInfo вспомогательная функция, принимающая один параметр и интерпретирующая его как дерево выражений И делегат без необходимости компилировать дерево выражений в делегат во время выполнения?

1 Ответ

1 голос
/ 31 августа 2010

Я не вижу способа, который был бы возможен. Делегат и выражение - это два разных типа объекта, которые просто выглядят одинаково. Это было бы сродни написанию:

  MyFunc("10m");

И если параметр обрабатывается как строка и как десятичное число без преобразования.

Лучше всего было бы вызвать Compile () и кэшировать результат. Я предполагаю, что вы уже планировали кэшировать результат поиска по выражению для свойства Name.

...