依存性注入の初心者向けの回答を投稿します。
以前の問題のあるコードは次のとおりです。
public class MyClassInvoker:IDisposable
{
readonly Timer _myTimer;
readonly MyClass _myclass;
public MyClassInvoker(Timer myTimer, MyClass myclass)
{
_myTimer = myTimer;
_myclass = myclass;
_myTimer.Interval = 3000;//configure Your timer here
_myTimer.Elapsed +=new ElapsedEventHandler(PeriodicInvoker);
}
public void Start()
{
_myTimer.Start();
}
public void Dispose()
{
_myTimer.Dispose();
}
void PeriodicInvoker(object sender, EventArgs e)
{
_myclass.DoSomePeriodicWork();
}
}
コードを修正すると、次のようになります。
public class MyClassInvoker:IDisposable
{
readonly Timer _myTimer;
readonly MyClass _myclass;
public MyClassInvoker(MyClass myclass)
{
_myTimer = new Timer();
_myclass = myclass;
}
public void Start()
{
_myTimer.Interval = 3000;//configure Your timer here
//add or remove any previous listeners
//here depending upon the business needs
_myTimer.Elapsed += new ElapsedEventHandler(PeriodicInvoker);
_myTimer.Start();
}
public void Dispose()
{
_myTimer.Dispose();
}
void PeriodicInvoker(object sender, EventArgs e)
{
_myclass.DoSomePeriodicWork();
}
}
問題について直感的に考えた後、分析を投稿しています。
- 私自身の質問に投稿されたリンクに従って、単純な割り当て以外にコンストラクターでこれ以上の作業を行わないでください。実際には、コンストラクターでイベント ハンドラーをバインドしていました。私がこのようにした場合、どのような影響があったかについて、今のところコメントすることはできません.
- テスト容易性を高めるために、前のコードで Timer オブジェクトを渡しました。
説明付きのソリューション
依存関係として Timer を渡すことで、.Net Timer BCL をモックするインターフェイスを提供して、Test をユニット化し、置換を提供しようとしました。現在、.Net には 3 種類のタイマーがあります。
- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer
これらのタイマーはどれも同じインターフェイスを共有していないため、それらを依存関係として渡すのは無意味です。これは、修正したコードで修正しました。
論理的に考えると、MyClassInvoker クラスをインスタンス化した後に Start メソッドが呼び出されるので、そこにイベント バインディングを配置すると、非常に理にかなっています。