具有强类型的模型继承

时间:2012-06-03 21:37:22

标签: .net inheritance object model

我有一个棘手的建模问题,我希望有另一种观点。

我正在处理一些被某些引擎视为整体的模型。它看起来像(名字不是我们正在使用的):

public class Container{
  // Some other specific properties and methods, ctor etc

  public IList<Group> Groups {get; private set;}

  // For convenience, we need that
  public IList<Element> Elements {get; private set;}
}

public class Group{
  // Specific stuff here      

  public IList<Element> Elements{get; private set;}

  public Container Container{get; set;}
}

public class Element{
  public Group Group {get; set;}
}

在整个模型中,我们都有这些双引用,因为模型被引擎视为一个整体。

现在,棘手的部分:我需要创建2个特定模型,共享这个组织。

目前,我有一个包含三个类的模型:Container - Group - Element。

我需要创建共享相同结构的特定模型,但是模型中包含特定的类。

  • BaseContainer,BaseGroup,BaseElement(parent)
  • ContainerFoo - GroupFoo - ElementFoo(第一个孩子)
  • ContainerBar - GroupBar - ElementBar(第二个孩子)

而且,要完成,最重要的是我需要强类型集合。例如,我需要ContainerFoo中的GroupFoo列表,而不是父类型的列表。

我探索了实现这一目标的两种方法:泛型和创建新属性。

例如:

public class BaseContainer<TGroup, TElement>{
  public IList<TGroup> Groups {get; private set;}

  public IList<TElement> Elements{get; private set;}  
}

public class BaseGroup<TContainer, TElement>{
  public TContainer Container {get; set;}

  public IList<TElement> Elements {get; private set;}
}

public class BaseElement<TGroup>{

  public TGroup Group{get; set;}

}

public class ContainerFoo: BaseContainer<GroupFoo, ElementFoo>{
  // Specific stuff here
}

public class GroupFoo: BaseGroup<ContainerFoo, ElementFoo>{
}

public class ElementFoo: BaseElement<ContainerFoo>{
}

此解决方案适用于这种情况,但是:

  • 容器中的类型列表可能很长,因为容器实际上是整个模型的入口点(这里简化)
  • 我们实际上无法使用protobuf-net,用于序列化和反序列化。

第二个解决方案:

 public abstract class BaseContainer{

  public abstract IList<BaseGroup> Groups {get;}

  public abstract IList<BaseElement> Elements{get;}  
}

public abstract class BaseGroup{
  public abstract BaseContainer Container {get; set;}
}

public abstract class BaseElement{

  public abstract BaseGroup Group{get; set;}
}

public ContainerFoo : BaseContainer{

  public override IList<BaseGroup> Groups {
    get{
      // We are using .Net 4, and we can do that.
      return (IList<BaseGroup>)this.GroupsFoo;
    }
  }

 public IList<GroupFoo> GroupsFoo{ get; private set;}

 // Same thing for elements
}

// You see the point, I don't want to create other classes here.

我认为你显然可以看到我对第二种解决方案不感兴趣!

还有什么想法?

1 个答案:

答案 0 :(得分:1)

您可以在派生类的属性上使用abstract/override修饰符,而不是使用new

class Container {
  public IList<Group> Groups { get; private set; }
}

class ContainerFoo : Container {
  public new IList<GroupFoo> Groups { get { return (IList<GroupFoo>)base.Groups; } }
}

或者,在这里使用遗产是否有任何实际好处?你最好定义一个通用的IContainer<T>接口并取消基类吗?

interface IContainer<TGroup> where T : Group {
  IList<TGroup> Groups { get; }
}

class ContainerFoo : IContainer<GroupFoo> {
  public IList<GroupFoo> Groups { get; private set; }
}

class ContainerBar : IContainer<GroupBar> {
  public IList<GroupBar> Groups { get; private set; }
}