我有三个班,他们都有一个属性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);
}
谢谢你的帮助!
此致 LEONA
答案 0 :(得分: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; }
}
答案 1 :(得分:6)
如果您无法实现界面并且不想使用反射,那么另一种解决方案可能是传递如何将日期传递给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);
}
}
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);
}
}
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);
}
}
Adam Ralph&#39;解决方案激励了我这个(我猜不是最好的,但它仍然有效)
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);
}
}
答案 2 :(得分:5)
另一种选择是动态构建Expression
。如果您不希望或不能将IDate
接口添加到模型对象,并且FindBy
需要Expression<Func<T, bool>>
(例如,它转换为{ {1}}内部用于EntityFramework或类似内容。
与@ JonB的答案一样,这没有编译时安全性,以确保IQueryable<T>.Where(...)
具有T
属性或字段。它只会在运行时失败。
Date
答案 3 :(得分:3)
假设对象列表不是很大,那么为3个类写一些通用的东西可能会过度工程化。 KISS
objects.Where(obj =>
(obj as Foo)?.DateTime == date ||
(obj as Bar)?.DateTime == date ||
(obj as Baz)?.DateTime == date)
答案 4 :(得分:1)
我不确定您的FindBy
方法的结构或返回方式,但您可以使用dynamic
关键字,如下所示:
var query=_genericRepository.FindBy(r=>((dynamic)r).Date==date);
如果FindBy
方法返回IEnumerable<T>
,那么您可能必须在return语句中添加.Cast<T>()
,否则您可能会得到IEnumerable<dynamic>
类型的<。 / p>
这绝不是类型安全的,如果T
没有Date
属性,您可能会遇到运行时错误。但这是一个值得考虑的选择。