Я пытаюсь написать вспомогательный класс, который представляет поля объекта.Вспомогательный класс должен иметь возможность одновременно получать значение поля в данном экземпляре и возвращать метаданные о базовом свойстве, которое он может получить с помощью отражения.
Я бы хотел, чтобы вспомогательный класс был созданСлужебный метод, вызываемый следующим образом:
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
вспомогательная функция, принимающая один параметр и интерпретирующая его как дерево выражений И делегат без необходимости компилировать дерево выражений в делегат во время выполнения?