Leo*_*ona 13 c# generics lambda
我有三个班,他们都有一个属性Date.我想编写一个泛型类来返回一个日期的所有记录.现在的问题是:如何使用泛型类型T编写lambda表达式?
代码简单如下(我不会编译,因为"r.Date"不起作用,但它是我想要实现的效果)
Class GenericService<T>: IGenericService<T> where T:class
{
...
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> GetRecordList(DateTime date)
{
var query=_genericRepository.FindBy(r=>r.Date=date);
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助!
此致,Léona
Kah*_*azi 14
编写一个接口,其中包含IDate和所有实体必须实现IDate和写入GenericService如下:
public class GenericService<T>: IGenericService<T> where T : class, IDate
{
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> 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; }
}
Run Code Online (Sandbox Code Playgroud)
如果你不能实现一个接口并且不想使用反射,另一个解决方案可能是传递如何获取GenericService的日期:
public class GenericService<T>: IGenericService<T> where T : class
{
public Func<T, DateTime> DateGetter { get; set; }
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> GetRecordList(DateTime date)
{
var query=_genericRepository.FindBy(r => DateGetter(r) == date);
}
}
Run Code Online (Sandbox Code Playgroud)
public class GenericService<T>: IGenericService<T> where T : class
{
Func<T, DateTime> _dateGetter;
public GenericService(..., Func<T, DateTime> dateGetter)
{
_dateGetter = dateGetter
...
}
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> GetRecordList(DateTime date)
{
var query=_genericRepository.FindBy(r => _dateGetter(r) == date);
}
}
Run Code Online (Sandbox Code Playgroud)
public class GenericService<T>: IGenericService<T> where T : class
{
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> GetRecordList(DateTime date, Func<T, DateTime> dateGetter)
{
var query=_genericRepository.FindBy(r => dateGetter(r) == date);
}
}
Run Code Online (Sandbox Code Playgroud)
Adam Ralph的解决方案激发了我的灵感(我猜不是最好的,但它仍然有效)
public class GenericService<T>: IGenericService<T> where T : class
{
public Dictionary<Type, Func<object, DateTime>> _dateGetter = new Dictionary<Type, Func<object, DateTime>>()
{
{ typeof(TypeWithDate), x => ((TypeWithDate)x).Date },
{ typeof(TypeWithDate2), x => ((TypeWithDate2)x).Date }
};
readonly IGenericRepository<T> _genericRepository;
public IEnumerable<T> GetRecordList(DateTime date)
{
var query=_genericRepository.FindBy(r => _dateGetter[typeof(T)](r) = date);
}
Run Code Online (Sandbox Code Playgroud)
}
另一种选择是Expression动态构建.这可能是有用的,如果你不想或不能添加一个IDate接口连接到模型对象,并且如果FindBy需要的Expression<Func<T, bool>>(例如,将其转换为IQueryable<T>.Where(...)内部进行的EntityFramework或相似.
与@ JonB的答案一样,这没有编译时安全性来确保T具有Date属性或字段.它只会在运行时失败.
public IEnumerable<T> 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<Func<T, bool>>(equalityExpression, parameterExpression);
var query = _genericRepository.FindBy(lambdaExpression);
return query;
}
Run Code Online (Sandbox Code Playgroud)