28

この質問への答えは非常に明白なので、誰もこれについて書くことを気にしませんでしたが、遅く、私は本当にこれについて頭を悩ませることができません。

私はIoCコンテナー(この場合はWindsor)を読んでいますが、コードのさまざまな部分からコンテナーと通信する方法がわかりません。

私はDIを取得し、poor mans DI(デフォルトのパラメーター実装でオーバーロードされたインジェクションコンストラクターを呼び出す空のコンストラクター)をしばらく行ってきましたが、コンテナーの利点を完全に確認できます。ただし、重要な情報が1つ欠けています。コンテナからのサービスが必要になるたびに、どのようにコンテナを参照することになっていますか?

渡す単一のグローバルな保険を作成しますか?絶対にありません!

私はこれを呼ぶべきだと知っています:

WindsorContainer container = new WindsorContainer(new XmlInterpreter());

(たとえば)XML構成をロードしたいのですが、コンテナーをどうすればよいですか?その後、毎回新しいコンテナを作成して、ロードされた構成を内部の静的マジックなどで永続化しますか、それとも毎回構成をリロードする必要がありますか(そうでないか、ライフサイクルが機能しませんでした)。

これを理解できないと、ライフサイクルがどのように機能するかを理解できなくなり、IoCの恐ろしさを使い続けることができなくなります。

ありがとう、

アンドリュー

4

5 に答える 5

24

99% のケースで、アプリごとに 1 つのコンテナー インスタンスです。通常、このように Application_Start (Web アプリの場合) で初期化します。

その後は、コンテナの消費者次第です。たとえば、モノレールASP.NET MVCなどの一部のフレームワークでは、インスタンス (この場合はコントローラー) の作成をインターセプトできるため、コントローラーとその依存関係をコンテナーに登録するだけで済みます。コンテナーが各コントローラーにその依存関係を注入するように要求します。たとえば、この ASP.NET MVC コントローラーを参照してください。これらのフレームワークでは、クラス内でコンテナーを呼び出したり参照したりする必要はほとんどありません。これは推奨される使用法です。

他のフレームワーク (Web フォームなど) では作成プロセスに簡単に参加できないため、このようなハックに頼るか、必要な依存関係を取得する (つまり、コンテナーを明示的に呼び出す) 必要があります。依存関係をプルするには、このようなコンテナーへの静的ゲートウェイまたはmaxnkで説明されているものを使用します。これを行うことで、実際にはコンテナーをサービス ロケーターとして使用していることに注意してください。これは、制御の反転だけでなく物事を切り離すこともありません。(ここここの違いを参照)

これで疑問が解消されることを願っています。

于 2008-12-15T03:10:40.490 に答える
3

通常、アプリケーション全体の存続期間中、インスタンスを 1 つだけ保持する必要があります。ほとんどの場合、アプリの起動時にコンテナーを初期化し、コンテナーを認識しないオブジェクトのプルに型指定されたファクトリを使用します。

他の一般的なアプローチは、コンテナー インスタンスを静的クラスでラップし、その静的クラスを使用して (シングルトン) コンテナーにアクセスすることです。Ayende の Rhino.Commons ライブラリでその例を見つけることができます。ただし、このアプローチには重大な欠点があり、避ける必要があります。

于 2008-12-22T22:15:15.337 に答える
1

Unity を使用して依存関係の構築を処理するために HttpModule を使用することに関する Michael Puleio のブログのこの例を使用します。http://blogs.msdn.com/mpuleio/archive/2008/07/17/proof-of-concept-a-simple-di-solution-for-asp-net-webforms.aspx

于 2008-12-15T14:19:55.663 に答える
0

私はこのインターフェースの実装を使用しています:

public interface IResolver
{
    object Resolve(Type type);
    object Resolve(string name);

    T Resolve<T>() where T : class;
    T Resolve<T>(string name) where T : class;
}

これは実際にはグローバル静的クラスにラップされています。次に例を示します。

public static class Resolver // : IResolver
{
    private static IResolver _current;

    public static object Resolve(Type type)
    {
        return Current.Resolve(type);
    }

    public static object Resolve(string name)
    {
        return Current.Resolve(name);
    }

    public static T Resolve<T>() where T : class
    {
        return Current.Resolve<T>();
    }

    public static T Resolve<T>(string name) where T : class
    {
        return Current.Resolve<T>(name);
    }

    private static IResolver Current
    {
        get
        {
            if (_current == null)
            {
                _current = new SpringResolver();
            }

            return _current;
        }
    }
}

また、私は単純なルールに従おうとしています-Resolverクラスの使用をできるだけ少なくし、代わりにそれらのサービスを必要とするオブジェクトにサービスを注入します。

于 2008-12-15T00:05:56.947 に答える