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つの特定のモデルを作成する必要があるということです。

現在、コンテナ-グループ-要素の3つのクラスを持つモデルがあります。

同じ構造を共有する特定のモデルを作成する必要がありますが、モデル全体に​​特定のクラスがあります。

  • BaseContainer、BaseGroup、BaseElement(親)
  • ContainerFoo-GroupFoo-ElementFoo(最初の子)
  • ContainerBar-GroupBar-ElementBar(2番目の子)

そして、完全を期すために、最も重要なことは、強く型付けされたコレクションが必要なことです。たとえば、親タイプのリストではなく、ContainerFooのGroupFooのリストが必要です。

これを実現する2つの方法を検討しました。ジェネリックスと新しいプロパティの作成です。

例えば:

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では実際には使用できません。

2番目の解決策:

 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.

この2番目の解決策について、私が気に入らない点をはっきりと理解できると思います。

これ以上のアイデアはありますか?

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 に答える