0

昨日仕事で非常に興味深い問題に出くわしました。

FooとBarという名前の2つの異なるクラスがあります。それぞれが独自のC#ライブラリプロジェクト(個別のdll)に座っています。

バーには仮想メソッドが含まれています。

public class Bar
{
     public virtual void DoSomething();
}

Fooは、コンストラクターでBarのインスタンスを使用して、内部プロパティを設定します。

public Foo (Bar myBar)
{
      m_Bar = myBar;
}

明らかに、FooにはBarのプロジェクトへの参照があります。

現在、他に5つのクラスがあり、それぞれが独自のproject/dllにあります。それらをA、B、C、D、およびEと呼びます。AEはすべてクラスBarからサブクラス化されており、それぞれにDoSomething()の独自のオーバーライドされた実装が含まれています。それらはBarからサブクラス化されているため、Fooのコンストラクターのパラメーターとして有効です。

AEはそれぞれ、Fooインスタンスの内部コレクションを維持します。たとえば、クラスA内で次のようなことを行います。

myFooCollection.Add(new Foo(this));

このため、クラスAEはすべてFooのproject/dllへの参照を必要とします。

ここで、しばらくFooに戻って、コンストラクターでBarプロパティを設定した後、そのBarのDoSomething()メソッドを呼び出す必要があるとします。

public class Foo (Bar myBar)
{
     m_Bar = myBar;
     m_Bar.DoSomething();
}

たとえば、クラスAがコンストラクターのBarパラメーターとして使用されたことを覚えておいてください。DoSomething()の呼び出しでは、そのメソッドのAの実装を実行する必要があります。ただし、コンストラクター引数は親クラスBarのものであり、FooはクラスAEの知識がないため(循環依存を引き起こさずに参照を与えることはできません)、親クラスBarの仮想メソッドを呼び出します。自然な解決策は、電話をかける前に子クラスにダウンキャストすることです。

(A)m_Bar.DoSomething();

しかし、これも問題外です。繰り返しになりますが、Fooはこの一連の子クラスについての知識を持っていません。これが私のジレンマです。明らかに、システムはここで紹介したものよりもはるかに大きく複雑であるため、プロジェクト全体の構造を変更することはできません。しかし、私の要件はまだ同じです。Fooが正しく機能するには、DoSomething()の子実装に到達できる必要があります。これを解決する方法について何か考えはありますか?問題をよりよく理解するために何らかの説明が必要な場合は、私に知らせてください。さらに詳しく説明します。

4

1 に答える 1

3

プロジェクトの静的循環参照を持つことは許可されていません。ただし、インスタンスの動的循環参照を持つことができます。次に呼び出すとm_Bar.DoSomething();、多態性のため、適切な実装が自動的に呼び出されます。の場合m_BarBarthenBarの実装が呼び出されます。の場合m_BarAthenAの実装が呼び出されます。を介してクラスの存在を知る必要Barもありません。FooAE


更新:(以下のコメントを参照)

public class A : Bar
{
     public override void DoSomething()
     {
         Console.WriteLine("I am an 'A'");
     }
}
于 2012-10-31T17:00:33.300 に答える