私は、依存性注入などの優れた機能を使用してアプリケーションを管理しやすくするために、アプリケーションのリファクタリングに取り組んできました。これを行うとき、私は循環依存に複数回遭遇しました。
したがって、これが周期的依存性の典型的な例です。
interface IA
{
int Data { get; }
}
interface IBefore
{
void DoStuffBefore();
}
class A: IA
{
public int Data { get; private set; }
IBefore before;
public A(IBefore before)
{
this.before = before;
}
public void Increment()
{
before.DoStuffBefore();
Data++;
}
}
class B: IBefore
{
IA a;
public B(IA a)
{
this.a = a;
}
public void WriteADataToConsole()
{
Console.Write(a.Data);
}
public void DoStuffBefore() //From IBefore
{
WriteADataToConsole();
}
}
お互いに必要なので、どちらのクラスも作成できません。ここで、この場合に行う標準(?)は、AのデータをAから分離することです。
public interface IA
{
int Data { get; set; }
}
public interface IBefore
{
void DoStuffBefore();
}
class AData : IA
{
public int Data { get; set; }
}
class A
{
public IA Data { get; private set; }
IBefore before;
public A(IA data, IBefore before)
{
this.Data = data;
this.before = before;
}
public void Increment()
{
before.DoStuffBefore();
Data.Data++;
}
}
class B : IBefore
{
IA a;
public B(IA a)
{
this.a = a;
}
public void WriteADataToConsole()
{
Console.Write(a.Data);
}
public void DoStuffBefore() //From IBefore
{
WriteADataToConsole();
}
}
上記は循環依存性を解決します。これは、最初にADataを作成してから、それをBに挿入し、BをAに挿入できるためです。ただし、BがリッスンできるイベントiIAを配置することもできます。
public interface IA
{
int Data { get; }
event Action BeforeEvent;
}
class A: IA
{
public int Data { get; private set; }
public event Action BeforeEvent;
public void Increment()
{
BeforeEvent();
Data++;
}
}
class B
{
IA a;
public B(IA a)
{
this.a = a;
a.BeforeEvent += new Action(WriteADataToConsole);
}
void WriteADataToConsole() //Event listener
{
Console.Write(a.Data);
}
}
イベントアプローチを依存性注入に変換しようとしていたので、これは私が偶然見つけたものです。そうすることで、循環依存を取得したことに気づきました。
私の脳を悩ませている質問のいくつかは次のとおりです。
- どちらのソリューションも循環依存関係を解決し(右?)、私が見る限り、Aを同程度に拡張できるようになっていますが、どちらが最良の設計と見なされますか?
- いつイベントを使用するか、いつDIを使用して循環依存関係を解決するか、および一般的には、どのようなガイドラインがありますか?
- 明らかに、AがBからの戻り値を必要とする場合、イベントは適切ではありません。つまり、voidが返される場合、イベントは常に優先されるということですか?
- 各ソリューションの長所と短所は何ですか?