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
インターフェースは多くのメンバーを持っており、そのための仮想プロキシを作成することは非常に面倒です
- ので、これはしかし、石英の場合には動作しません。
IScheduler
のすべてのメンバーが非同期である必要がありますが、非同期ではないものがかなりあります(IsStarted
など)。したがって、アプリケーション固有の抽象化を作成する方がはるかに理にかなっています。
これは、非同期アプリケーション固有の抽象化の背後でIScheduler
の使用を非表示にすることを意味します。この抽象化によって、スケジューラの操作の複雑さが隠され、そのメソッドを非同期にすることで、この新しい抽象化の実装によって遅延スケジューラを作成できるようになります。この実装は、スケジューラーの複雑さを隠すアダプターになります。
関連:https://stackoverflow.com/questions/45924027/avoiding-all-di-antipatterns-for-types-requiring-asynchronous-initialization – Steven