web-dev-qa-db-ja.com

ASP.Net Coreでは、循環参照をどのように解決しますか?

静的ロガーと静的メールサービスを使用するプロジェクトの移行に取り組んでいました。
メールサービスは送信されたメールをログに記録し、ロガーサービスはログの問題(DBダウンなど)がある場合にメールを送信します。メールサービスが失敗した場合、問題を記録することもできます。

ロガーが失敗した場合、メール通知を送信しようとしますが、メールサービスが失敗した場合(そもそもロガーが呼び出された理由である可能性があります)、続行して問題をログファイルに書き込みます。

Email Service <--statically references--> Logger Service

問題は、両方の「サービス」がシングルトンであり、コンストラクタパラメータとして相互に参照する必要があることです。私の最初の考えはプロパティベースの注入でしたが、それは非常に望ましくない一時的なカップリングの状況であるとすぐにわかりました。

現在実行中の主なアイデアは、ログレベルで、サービスプロバイダーを呼び出して電子メールサービスを作成することです(これにより、シングルトンインスタンスが取得されます)が、実際には、クラスライブラリも。注入システム。私が何かを見逃している場合に備えて、誰かが何か推奨事項を持っていますか?

編集:さらに検討した結果、別のサービスを注入できる独自の(基本的な)抽象化されたサービスプロバイダーを作成することはおそらく意味がありますか?そうすれば、私はおそらくそのような場合には代わりにそれを渡すことができます。

6
James Wilkins

Mark Seemannによる_C#_ 依存性注入 についての素晴らしい本を読むことをお勧めします。さまざまなタスクの実際のサンプルがたくさんあります。あなたの場合と同様の循環依存関係があっても、それを行うことができます。

一般的に、メインのデザインルールは_You can't resolve the problem on its level_であり、この場合も同様です。 2つのロガー間の相互作用を解決するには、ここに本当に メディエーター が必要です。両方の状態を簡単に保存し、変更をお互いに通知することができます。

たとえば、次のようにメッセージにTargetを導入できます。

_GeneralMessage // both loggers got this
EmailMessage // only email logger got this
LoggerMessage // only logger got this
_

したがって、いずれかのロガーで問題が発生した場合、メディエーターは対応するタイプのメッセージを送信して、問題について他のロガーに通知します。

そのような最先端のロジックの一般的なアプローチは、AOP実装です(個人的には PostSharp を好んでいます)。クラスにアスペクトを割り当てる従来の手法を使用した場合でも、一般的なアプローチ)。

_.Net Core_インジェクションシステムからのコードの分離については、_Logger Factory_を調べることをお勧めします。

新しいフレームワークは、プロバイダーとして必要なロギングフレームワークを使用できるようにする抽象化レイヤーまたはラッパーを作成します。これにより、開発者としての作業において最大限の柔軟性を確保できます。さらに、それは_.NET Core_でのみ利用可能ですが、標準のVisualの場合は _.NET Core_ のような_Microsoft.Extensions.Logging_ NuGetパッケージを参照しますStudio _.NET 4.6_プロジェクトは問題ありません。

_Logger Factory_を使用すると、メッセージを フィルタリング して、すべてのロガーに他のロガーの問題を通知することもできます OSイベントログ などに接続します。

6
VMAtm

循環依存関係を維持したいが循環参照エラーを処理しているのか、循環依存関係の代替手段を求めているのかはわかりません。

循環依存関係が好きで、それを実装する方法がわからない場合は、 nity、この記事で説明されているように で問題を解決できます。

循環依存関係が気に入らない(私も気に入らない)場合は、以下にいくつかのアイデアを示します。

  1. シングルトンを取り除く。そのパターンは2005年頃に人気がありましたが、最近では 本当に悪いと考えられています です。特にユニットテストにはひどい。

  2. ロギングサービスがメールを送信しないようにする必要があります。 1つのこと: ログへの書き込みを実行できるようにする必要があります。それでおしまい。

  3. ロギングサービスは、失敗しないように十分にシンプルでなければなりません。おそらくメモリ不足でない限り、その場合はメールも送信できません。

  4. 必要に応じて、ログを永続させる別のサービスを使用できます。たとえば、ディスクにコミットするか、本当に必要な場合はメールを送信します。ただし、ログライターとは別にする必要があります。

  5. 本当に凝ったものにしたい場合は、 チェーンの責任パターン を使用して、ログを永続化できるいくつかのサービスを使用できます。これにより、フェイルオーバー機能が可能になります。たとえば、ログがデータベースに永続化される可能性があります。 SQL接続が失敗した場合、それらはフラットファイルに格納されます。フラットファイルがいっぱいの場合は、電子メールが送信されます。多分あなたはそれを後のバージョンで行うことができます:)

上記は、「ログ」とは、たとえば監査ログとは対照的に、ある種の「デバッグログ」を意味すると想定しています。規制上の理由から、ミッションクリティカルではるかに複雑になる可能性があります。

3
John Wu