Проблема в том, что вы можете вывести тип результата string
из свойства, но вам все равно придется указать его в аргументах типа, потому что вы также должны указать Product
.
Хороший способ приблизиться к этому - это типизированная запись данных:
IDataRecord<Product> productRecord = ...;
string name = productRecord.ReadValue(p => p.Name);
Это кажется возможным, потому что в контексте ORM, подобном тому, который вы подразумеваете, вы должны знать тип данных, представленный записью.
Самая сложная часть - это ...
в приведенном выше коде. Это требует некоторой инфраструктуры, но вы должны написать ее только один раз, и вы можете использовать ее везде. Первым шагом является получение типизированной записи данных:
public interface IDataRecord<T> : IDataRecord
{
TValue GetValue<TValue>(Expression<Func<T, TValue>> getter);
}
Затем реализуйте запись типизированных данных, используя шаблон Декоратор (скучно, но прямо):
public class DataRecord<T> : IDataRecord<T>
{
private readonly IDataRecord _untypedRecord;
public DataRecord(IDataRecord untypedRecord)
{
_untypedRecord = untypedRecord;
}
public TValue GetValue<TValue>(Expression<Func<T, TValue>> getter)
{
...the original code...
}
...pass through all other members to the untyped record...
}
Наконец, добавьте преобразование из нетипизированной в типизированную запись:
public static class TypedDataRecords
{
public static IDataRecord<T> TypedAs<T>(this IDataRecord untypedRecord)
{
return new DataRecord<T>(untypedRecord);
}
}
Теперь пример выглядит так:
IDataRecord<Product> productRecord = record.TypedAs<Product>();
string name = productRecord.ReadValue(p => p.Name);
decimal price = productRecord.ReadValue(p => p.Price);
...