说我有以下代码:
public class Pond
{
public List<Frog> Frogs { get; set; }
public List<MudSkipper> MudSkippers { get; set; }
public List<Eel> Eels { get; set; }
}
public class Frog: IAquaticLife
{
}
public class MudSkipper: IAquaticLife
{
}
public class Eel: IAquaticLife
{
}
现在我想编写一个通用方法,用于某个池塘返回这些类型的列表:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return Uow.GetByID<Pond>(pondId).Eels;
}
好的,所以我在那里将返回那个池塘里的所有鳗鱼。我想要做的是返回所有的T。
所以,如果我打电话给GetByPond<MudSkipper>(1)
那将会返回所有的mudskippers。
任何人都知道怎么做?
答案 0 :(得分:5)
像
这样的东西public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return from t in Uow.GetByID<Pond>(pondId).AquaticLife()
where (typeof(t) == typeof(T)) select t;
}
或简单地(使用@DStanley在更改答案之前指出的方法)
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
return Uow.GetByID<Pond>(pondId).AquaticLife().OfType<T>();
}
这需要 Uow.GetByID(int id)来返回特定池塘中实现 IAquaticLife 的所有类型的生物。但另一种方法是,您将 IAquaticLife 的各种实现者的知识硬编码到您的通用方法中。这不是一个好主意。
<强>更新强>
目前 Pond 有 Eels , Mudskippers 等单独的集合。如果你想添加更多实现<的东西,那就变得脆弱了em> IAquaticLife 随着你的代码的发展,因为你必须改变 Pond 和上面的通用方法。
我建议您不要使用单独的方法来处理每种类型的水生生物,而是使用一种方法返回池塘中实现 IAquaticLife 的所有方法,例如
public class Pond
{
public IEnumerable<IAquaticLife> AquaticLife() { ... }
}
我已经用这个假设更新了上面的代码。
任何拥有Pond实例但想要获得的人都可以这样做:
var eels = pond.AquaticLife().OfType<Eels>();
答案 1 :(得分:2)
试试这个:
return Uow.GetByID<Pond>(pondId).OfType<T>();
击> <击> 撞击>
修改强>
由于您已将集合放在单独的属性中,因此可以使用switch
块根据类型返回正确的属性,或使用反射根据类型名称获取属性。
基于您的要求的更好的设计是拥有一个私有的List<IAquaticLife>
来存储所有的生物而不是单独的属性,但我会假设您现在不能这样做。
交换机的一个例子是:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
switch(typeof(T))
{
case typeof(Eel):
return Uow.GetByID<Pond>(pondId).Eels;
//etc.
default:
throw new ApplicationException(string.Format("No property of type {0} found",typeof(T).Name));
}
}
答案 2 :(得分:-1)
public Pond GetByPond(int pondId)
{
return Uow.GetByID<Pond>(pondId);
}
如果你想要你的青蛙,请执行:
var frogs = xxx.GetByPond(1).Frogs;
如果你想要你的MudSkippers,请执行:
var mudSkippers = xxx.GetByPond(1).MudSkippers;
等等。
如果您可以致电GetByPond<Frog>(1)
,则可以致电GetByPond(1).Frogs
。
如果在任何情况下你都不知道T
,你需要创建所有这些的集合并按类型过滤它们。如果您有中间子类型,这也很有用:
public IEnumerable<T> GetByPond<T>(int pondId) where T : IAquaticLife
{
var pond = Uow.GetByID<Pond>(pondId);
var life = pond.Frogs.Union(pond.Eels).Union(pond.MudSkippers);
return life.OfType<T>();
}
但是你正在连接集合只是为了过滤它们。