C#lambda查询使用generics类型

我有三个class,他们都有财产日期。 我想写一个generics类来返回一个日期的所有记录。 现在的问题是:如何使用generics类型T编写lambda表达式?

代码简单如下(我不会编译,因为“r.Date”不起作用,但它是我想要实现的效果)

Class GenericService: IGenericService where T:class { ... readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date) { var query=_genericRepository.FindBy(r=>r.Date=date); } 

谢谢你的帮助!

此致,Léona

另一种选择是动态构建Expression 。 如果您不想或不能将IDate接口添加到模型对象,并且如果FindBy需要Expression> (例如,它转换为IQueryable.Where(...) ,则此function非常有用IQueryable.Where(...)内部为EntityFramework或类似。

与@ JonB的答案一样,这没有编译时安全性来确保T具有Date属性或字段。 它只会在运行时失败。

 public IEnumerable GetRecordList(DateTime date) { var parameterExpression = Expression.Parameter(typeof(T), "object"); var propertyOrFieldExpression = Expression.PropertyOrField(parameterExpression, "Date"); var equalityExpression = Expression.Equal(propertyOrFieldExpression, Expression.Constant(date, typeof(DateTime))); var lambdaExpression = Expression.Lambda>(equalityExpression, parameterExpression); var query = _genericRepository.FindBy(lambdaExpression); return query; } 

编写一个具有IDate的接口,所有实体都必须实现IDate并编写GenericService如下所示:

 public class GenericService: IGenericService where T : class, IDate { readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date) { var query=_genericRepository.FindBy(r => r.Date = date); } } public interface IDate { DateTime Date{ set; get; } } public class Entity : IDate { DateTime Date { set; get; } } 

另一种解决方案,如果你不能实现一个接口而又不想使用reflection,可以传递如何将日期传递给GenericService:

由财产:

 public class GenericService: IGenericService where T : class { public Func DateGetter { get; set; } readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date) { var query=_genericRepository.FindBy(r => DateGetter(r) == date); } } 

由构造函数:

 public class GenericService: IGenericService where T : class { Func _dateGetter; public GenericService(..., Func dateGetter) { _dateGetter = dateGetter ... } readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date) { var query=_genericRepository.FindBy(r => _dateGetter(r) == date); } } 

通过方法本身:

 public class GenericService: IGenericService where T : class { readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date, Func dateGetter) { var query=_genericRepository.FindBy(r => dateGetter(r) == date); } } 

按类型:

亚当拉尔夫的解决方案激励了我这个(我猜不是最好的,但它仍然有效)

 public class GenericService: IGenericService where T : class { public Dictionary> _dateGetter = new Dictionary>() { { typeof(TypeWithDate), x => ((TypeWithDate)x).Date }, { typeof(TypeWithDate2), x => ((TypeWithDate2)x).Date } }; readonly IGenericRepository _genericRepository; public IEnumerable GetRecordList(DateTime date) { var query=_genericRepository.FindBy(r => _dateGetter[typeof(T)](r) = date); } 

}

假设对象列表不是很大,那么为3个类写一些通用的东西可能会过度工程化。 吻 。

 objects.Where(obj => (obj as Foo)?.DateTime == date || (obj as Bar)?.DateTime == date || (obj as Baz)?.DateTime == date) 

我不确定您的FindBy方法是如何构造的或它返回的是什么,但您可能能够像这样使用dynamic关键字:

  var query=_genericRepository.FindBy(r=>((dynamic)r).Date==date); 

如果FindBy方法返回IEnumerable ,那么您可能必须在return语句中添加.Cast() ,否则您可能会得到一种IEnumerable

这绝不是类型安全的,如果T没有Date属性,您可能会遇到运行时错误。 但这是一个值得考虑的选择。