Метод расширения, который принимает выражение Expression <Func <T>> как параметр
Я использую .NET4.5
и C#
Мне понравилось создание метода расширения, который позволил бы мне передать свойство объекта, и если Id этого объекта равен 0, тогда return null
в противном случае вернет это значение свойства.
Я мог бы сделать это без проблем с отражением, поэтому рассмотрим это больше упражнений по обучению, а не меня, пытаясь решить реальную проблему.
В настоящее время метод расширения находится в классе static
, который выглядит следующим образом:
public static object GetNullIfNotSet(this WillAnswer answer, Expression<Func<WillAnswer>> expression)
{
if (answer.Id == 0) return null;
return expression.Compile()();
}
Способ, которым я хочу использовать его, следующий (ответ имеет тип WillAnswer
):
var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets)
Однако это дает мне ошибку компиляции:
Ошибка 1 Делегат 'System.Func' не принимает 1 аргументы C:\hg\Website\Areas\Wills\ViewModel\Answers.cs 38 59 Веб-сайт ![введите описание изображения здесь]()
Что заставляет меня хмуриться, так как я не думаю, что передаю какие-либо аргументы (я?). Может ли кто-нибудь умнее меня объяснить, какие из моих ожиданий ошибочны.
На всякий случай я был неясен, я повторю. Я хочу, чтобы я мог позвонить var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets)
и получите null
, если Id
of answer
- 0
.
Ответы
Ответ 1
Нет необходимости в Expression
вообще, просто используйте Func<WillAnswer, TProp>
:
public static TProp GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
if (answer.Id == 0) return default(TProp);
return func(answer);
}
Обратите внимание, что это не всегда возвращает null
, но значение по умолчанию (в случае, если свойство является значением типа).
Обновить (согласно вашему запросу):
Чтобы иметь возможность возвращать null
для всех переданных свойств, сигнатура метода была изменена вместо return object
:
public static object GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
if (answer.Id == 0) return null;
return func(answer);
}
Но вы потеряете преимущества дженериков, и в итоге вы получите явные приведения к Nullable<T>
:
var emptyIfNewObject = (bool?)answer.GetNullIfNotSet(o => o.HasBusinessAssets)
Что менее идеально.
Ответ 2
Кажется, вам нужно Func<WillAnswer, T>
не выражение:
public static T GetDefaultIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) {
if (null == answer)
throw new ArgumentNullException("answer");
else if (null == func)
throw new ArgumentNullException("func");
return answer.Id == 0 ? return default(T) : func(answer);
}
EDIT: если вы хотите обеспечить null
, вы можете ограничить общий T
:
public static T GetNullIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func)
where T: class { // no structs here
if (null == answer)
throw new ArgumentNullException("answer");
else if (null == func)
throw new ArgumentNullException("func");
return answer.Id == 0 ? return null : func(answer);
}