注: 次のアドバイスはすべての IoC フレームワークに当てはまり、Unity に固有のものではありません。
TLDR : これをしないでください。コンテナーを一度登録し、一度だけApplication_Start
呼び出しますServiceLocator.SetLocatorProvider
。
「リクエストごと」または「Web リクエストごと」の有効期間を持つように依存関係を登録しても問題ありません。ただし、Web リクエストごとに新しいコンテナー インスタンスを作成することは、非常に悪い習慣です。
コンテナーは、(登録用ではなく) インスタンスの解決用に最適化されています。これは、(コンテナーから) 型が初めて要求されたときに、内部で動的コード生成が行われることが多いことを意味します。登録とコード生成およびコンパイル プロセスはかなり時間がかかる可能性があり、Web 要求ごとにコンテナーの新しいインスタンスを作成すると、完全な登録とコード生成プロセスが最初からやり直されます。これには時間がかかり、多くの一時オブジェクトが生成され (より多くのガベージが収集されます)、少なくともそのコンテナー インスタンスの存続期間中にキャッシュする必要がある新しいコードが生成されます。
さらに、複数のコンテナー インスタンスがあると、Web 要求ごとよりも大きなスコープでインスタンスを登録するなど、他の最適化を行うことが難しくなります。あなたの場合、タイプを「シングルトン」として登録することは、そのタイプがそのコンテナインスタンスのコンテキスト内でシングルトンであるため、実際には「Webリクエストごと」を意味します。または、パフォーマンスを考慮しなくても、一部の型が正しく機能するには、「Web 要求ごと」よりも長い有効期間 (アプリ ドメインごとに 1 つのインスタンスなど) が必要になり、構成が難しくなります。
リクエストごとにコンテナーを使用しても、おそらくこれを行うことができますが、コードの保守ははるかに困難になります。
コンテナー自体はスレッドセーフであるため、その意味では、要求ごとにコンテナー インスタンスを用意する必要はありません。
そして、あなたの場合、リクエストごとに変更するため、コードに競合状態、同時実行バグがあるため、さらに悪いことです。ServiceLocator
はServiceLocator
、登録されたデリゲートをプライベートな静的フィールドに格納します。これは、すべてのスレッドからアクセスできることを意味します。つまり、ウェブ リクエストを介してコンテナ インスタンスを共有しています。一度に 1 つの Web リクエストが発生するため、開発中にはおそらく気付かないでしょうが、コード呼び出しServiceLocator.Current
がある場合、本番環境では失敗します。たとえば、リクエスト 1 が開始され、サービス ロケータが設定される次の非常に可能性の高いシナリオを考えてみましょう。その後、リクエスト 2 が開始され、独自のコンテナー インスタンスでサービス ロケーターがオーバーライドされます。その後、リクエスト 1 のコードが呼び出されますServiceLocator.Current
これで、2 番目のリクエストのコンテナーが返されます。時々(運が良ければ)ObjectDisposedException
. これは、別のスレッドがまだ (誤って) 使用しているコンテナーをスレッドが破棄した場合に発生します。ただし、別の Web リクエスト (複数のスレッドで使用するのは安全ではないインスタンス) に属する型が解決されることがあります。DataContext
たとえば、LINQ to SQLまたは Entity Frameworkインスタンスを返す場合ObjectContext
などです。これらのクラスは通常、Web リクエストごとに構成する必要があり、複数のスレッドで共有することはできません。