1

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

我正在处理一个被某些引擎作为一个整体对待的模型。看起来像这样(名称不是我们使用的名称):

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(父级)
  • 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.

我认为您显然可以看到我不喜欢第二种解决方案的地方!

还有什么想法吗?

4

1 回答 1

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; }
}
于 2012-06-03T21:53:10.670 回答