Лично я предпочитаю перегрузку Expression.Property
, которая принимает PropertyInfo
экземпляр .
. Для этого вы можете сделать следующее:
ParameterExpression param = Expression.Parameter(typeof(TE), "ent");
MemberExpression prop = Expression.
Property(param, typeof(TE).GetProperty("TimeStamp"));
Expression<Func<TE, DateTime>> lambda = Expression.Lambda<Func<TE, DateTime>>(
prop, new ParameterExpression[] { param });
DateTime maxdate = this.EntityCollection.Select(lambda).Max();
Это намного чище.
Возможно, что вызов Type.GetProperty
ничего не возвращает, и это дает вам ошибку.Помните, что имя свойства, передаваемое в качестве параметра, должно быть общедоступным, в противном случае вам нужно использовать перегрузку GetProperty
, которая позволяет указывать значения из перечисления BindingFlags
, чтобы указать, что вы хотите не-общественные свойства должны быть включены.
Однако я думаю, что есть лучшая альтернатива.Вы должны определить интерфейс следующим образом:
public interface IHaveTimestamp
{
DateTime TimeStamp { get; set; }
}
Это позволит вам затем определить метод расширения следующим образом:
public static DateTime? MaxTimeStamp(IEnumerable<T> entities)
where T : IHaveTimeStamp
{
// Return the max.
return entities.Select(e => (DateTime?) e.TimeStamp).Max();
}
Примечание: DateTime?
используется вместо DateTime
в случае, если у вас есть пустая последовательность.Кроме того, вы можете создать перегрузку, которая принимает IQueryable<T>
, если вы хотите, чтобы выполнение происходило на сервере.
Основное преимущество, которое вы получаете здесь, заключается в том, что вы получаете проверку во время компиляциигде звонки действительны.Это намного лучше, чем генерировать исключение во время выполнения.
Кроме того, это не составит труда реализовать;вы используете Entity Framework, которая создает частичные файлы классов ;из-за этого легко добавить еще один частичный файл класса для каждого типа, который имеет это:
public partial class MyEntity : IHaveTimeStamp
{ }
Ваш исходный код указывает, что у вас уже есть свойство TimeStamp
для каждого из объектов, которые вы хотитеиспользуйте этот метод расширения, потому что вам не нужно ничего делать для реализации интерфейса, он уже неявно реализован для вас, потому что свойство TimeStamp
должно быть открытым.
Если это не общедоступно, то вы можете легко изменить свое определение следующим образом:
public partial class MyEntity : IHaveTimeStamp
{
IHaveTimeStamp.TimeStamp
{
get { return this.TimeStamp; }
set { this.TimeStamp = value; }
}
}
В любом случае, это простое задание копирования и вставки с некоторыми изменениями классаимя каждый раз.