2017-09-24 10 views
2

シンプルインジェクタを使用するためにQuartzライブラリを設定していますが、正しく登録することに問題があります。問題はGetScheduler()は非同期であり、このコードは非同期であるシンプルなインジェクターでファクトリメソッドを登録する方法ISchedulerシンプルインジェクタの非同期工場

container.Register(async() => 
{ 
     return await container.GetInstance<ISchedulerFactory>().GetScheduler(); 
}); 

Task<IScheduler>がない登録されていることでしょうか?もちろん、ResultTaskを使用して結果を待つことができますが、他の方法がありますか?

+0

関連:https://stackoverflow.com/questions/45924027/avoiding-all-di-antipatterns-for-types-requiring-asynchronous-initialization – Steven

答えて

4

Task<ISceduler>を登録して注入することはできますが、GetInstanceメソッドは同期的なので、シンプルインジェクタは非同期ファクトリメソッドの登録をサポートしていません。

実際、DIコンテナはこれをサポートしておらず、どちらもサポートしていません。オブジェクトの構成はfast and reliableであり、オブジェクトの構成中にI/O操作は行われません。

オブジェクト合成中にI/O(および非同期)操作を実行すると、操作が遅くなり、信頼性が低くなります(その間に外部I/Oリソースが使用可能でなければならないため) 。

代わりに、非同期操作はオブジェクト合成前またはオブジェクト合成後に移動する必要があります。 Object Compositionの前には、アプリケーションの起動中に、つまり一度のスタートアップ初期化を意味する一方で、Object Composition後に発生する非同期操作は、構築されたオブジェクトグラフ上のコンポーネントに対する呼び出しによってトリガされます。

お客様の場合、正しい解決策はいくつかの要因によって異なります。

アプリケーションでのみ、アプリケーション内の1つのISchedulerを必要とする場合は、アプリケーションの起動時に一度factory.GetSchedulerを呼び出し、コンテナにSingletonようISchedulerを登録してもいいかもしれません。 Here's a related discussionについて非同期スタートアップの初期化について

しかしISchedulerはシングルトンことができない場合は、これは(それはおそらく既にあるもの)、非同期になるためにISchedulerニーズを使用してコードを意味します。 ISchedulerを使用する必要のあるコンポーネントにISchedulerFactoryを注入する必要があるかもしれません。この方法でGetSchedulerメソッドを待つことができます。

もう1つの一般的なオプションは、作業している抽象化のVirtual Proxy実装を作成することです(この場合はIScheduler)。 ISchedulerインターフェースは多くのメンバーを持っており、そのための仮想プロキシを作成することは非常に面倒です

  1. ので、これはしかし、石英の場合には動作しません。
  2. ISchedulerのすべてのメンバーが非同期である必要がありますが、非同期ではないものがかなりあります(IsStartedなど)。したがって、アプリケーション固有の抽象化を作成する方がはるかに理にかなっています。

これは、非同期アプリケーション固有の抽象化の背後でISchedulerの使用を非表示にすることを意味します。この抽象化によって、スケジューラの操作の複雑さが隠され、そのメソッドを非同期にすることで、この新しい抽象化の実装によって遅延スケジューラを作成できるようになります。この実装は、スケジューラーの複雑さを隠すアダプターになります。

関連する問題