Chr*_*ris 8 c# oop entity-framework
我有一个应用程序,它有一个概念,Venue即事件发生的地方.A Venue有很多个VenuePart.所以,它看起来像这样:
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
A Venue可以GolfCourseVenue是a Venue,具有Slope和特定类型的VenueParta HoleVenuePart:
public class GolfCourseVenue : Venue
{
public string Slope { get; set; }
public virtual ICollection<HoleVenuePart> Holes { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在未来,可能还有其他种类的Venues都继承自Venue.他们可能会添加自己的字段,并且将始终具有VenuePart自己的特定类型.
以下是VenuePart课程:
public abstract class VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get { return "Hole"; } }
public int Yardage { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我上面的声明似乎是错误的,因为现在我有一个GolfCourseVenue有两个集合,真的应该只有一个.我无法覆盖它,因为类型不同,对吧?当我运行报告时,我想通常引用这些类,我只是吐出Venues和VenueParts.但是,当我渲染表格等时,我想具体一点.
我有很多像这样的关系,我想知道我做错了什么.例如,我有一个Order有OrderItemS,也是特定种类的OrderS作特定种类的OrderItem秒.
更新:我应该注意这些类是实体框架代码优先实体.我希望这没关系,但我想可能会这样.我需要以Code-First可以正确创建表的方式构造类.它看起来不像Code-First可以处理泛型.对不起,这个实现细节正在妨碍优雅的解决方案:/
更新2:有人链接到指向协方差和逆变的搜索,这似乎是一种将子类型中的列表限制为给定子类型的方法.这似乎很有希望,但这个人删除了他们的答案!有没有人知道如何利用这些概念?
更新3:删除了子对象中的导航属性,因为它使人们感到困惑并且没有帮助描述问题.
这是使用泛型的一种可能的选择:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue<T> where T : VenuePart
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<T> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue<HoleVenuePart>
{
}
Run Code Online (Sandbox Code Playgroud)
这里 GolfCourseVenue 有集合 VenueParts,它可以包含 HoleVenueParts 或超类 HoleVenueParts。Venue 的其他专业化会将 VenueParts 限制为包含特定于该场地的 VenueParts。
第二种可能性与你的情况差不多
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public string NameDescriptor { get{return "I'm a hole venue"; } }
}
public class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<VenuePart> VenueParts { get; set; }
}
public class GolfCourseVenue : Venue
{
}
Run Code Online (Sandbox Code Playgroud)
现在 GolfCourseVenue 具有 VenueParts 集合,它可以包含 VenueParts 或超类 VenueParts。这里,Venue 的所有专业化都可以包含任何类型的 VenuePart,这可能适合也可能不适合。
为了回答您关于协方差的评论,我会提出这样的建议:
public abstract class VenuePart
{
public abstract string NameDescriptor { get; }
}
public class HoleVenuePart : VenuePart
{
public override string NameDescriptor { get{return "I'm a hole venue"; } }
}
public abstract class Venue
{
public int Id { get; set; }
public string Name { get; set; }
public abstract ICollection<VenuePart> VenueParts { get; }
}
public class GolfCourseVenue : Venue
{
private ICollection<HoleVenuePart> _holeVenueParts;
public GolfCourseVenue(ICollection<HoleVenuePart> parts)
{
_holeVenueParts = parts;
}
public override ICollection<VenuePart> VenueParts
{
get
{
// Here we need to prevent clients adding
// new VenuePart to the VenueParts collection.
// They have to use Add(HoleVenuePart part).
// Unfortunately only interfaces are covariant not types.
return new ReadOnlyCollection<VenuePart>(
_holeVenueParts.OfType<VenuePart>().ToList());
}
}
public void Add(HoleVenuePart part) { _holeVenueParts.Add(part); }
}
Run Code Online (Sandbox Code Playgroud)