1

私は、Web アプリに IoC を実装するための詳細を調べてきましたが、Microsoft.Practices.ServiceLocation を活用する方法で行いました。私は特に Autofac と asp.net の統合を使用していますが、他のコンテナーに対して自分自身を開いたままにしたかったのです。この質問の行に沿って、Web アプリ コードでコンテナーにアクセスする方法が心配でした。

主に解決するインターフェイスを定義する「コア」ライブラリがあります。このコア ライブラリは、私の Web アプリや他のアプリでも使用されています。共通のインターフェースを定義すると非常に便利です。これは、IoC コンテナーへのアクセスを配置するのに最適な場所だと思い、静的クラスを使用して実行しました。トリックは、コンテナを静的クラスに注入することです。

Web 環境ではコンテナがリクエストごとに異なる可能性があるため注意が必要ですが、Web 以外のアプリでは常に同じになる可能性があります。最初はコンテナにメソッドを直接注入しようとしましたが、次の Web リクエストですぐに失敗しました。だから私はこれを思いついた:

public static class IoCContainer
{
    public static void SetServiceLocator(Func<IServiceLocator> getLocator)
    {
        m_GetLocator = getLocator;
    }
    static private Func<IServiceLocator> m_GetLocator = null;

    public static T GetInstance<T>(string typeName)
    {
        return m_GetLocator().GetInstance<T>(typeName);
    }
}

今私のglobal.asax.csでこれを行います:

protected void Application_Start(object sender, EventArgs e)
{
    var builder = new Autofac.Builder.ContainerBuilder();
    ... register stuff ...
    var container = builder.Build();
    _containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
    Xyz.Core.IoCContainer.SetServiceLocator(() => 
        new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
            (_containerProvider.RequestContainer));
}
public IContainerProvider ContainerProvider
{
    get { return _containerProvider; }
}
static IContainerProvider _containerProvider;

そして、依存関係を解決するための呼び出しは次のようになります

var someService = Xyz.Core.GetInstance<ISomeService>();

したがって、特定のコンテナーを渡すのではなく、コンテナーを取得する方法を知っているデリゲートを渡します。非 Web アプリケーションの場合、デリゲートはおそらく build() が提供するものを返すだけです。

専門家への私の質問は、これは理にかなっていますか? コンテナー製品が何であるか、またはコンテナー自体がどこから来たのかを知らなくても、依存関係を解決できるものにたどり着く簡単な方法があります。どう思いますか?

4

1 に答える 1

2

IoC が非 DI アーキテクチャに導入されたため、同様のパターンを使用しています。したがって、コンテナを明示的に呼び出してサービスを取得できるようにする必要があります。これは基本的に Factory パターンです。

IoC の真の利点は、すべての依存関係を注入でき、コードがサービス ロケーターに依存しなくなったときに実現されます。Autofac.Integration.Web には、静的サービス ロケーターを廃止するページ オブジェクトへの挿入を実行するハンドラーがあります。私はこれが好ましい方法ですが、(私たちの場合と同様に)サービスロケーターは常に回避できるとは限りません。

とはいえ、IoCContainer クラスを使用してコンテナーからアプリを既に分離しているので、IoCContainer 内に AutofacServiceLocator の追加の抽象化を行う理由はないと思います。結論として、IoCContainer は既にサービス ロケーターであり、コンテナー実装への直接アクセスを "許可" する必要があります。

これがあなたのサービスロケータークラスに対する私の見解です:

public static class IoCContainer
{
    private static IContext GetContainer()
    {
        var cpa = 
             (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
        return cpa.ContainerProvider.RequestContainer;
    }

    public static T GetInstance<T>()
    {
        return GetContainer().Resolve<T>();
    }
}
于 2009-10-08T08:55:16.020 に答える