0

そこで、私は新しいプロジェクトを開始し、過去数年間に学んだいくつかのことを実装しようとしています。その最初のプロジェクトは、IoCにCastleを使用することです。

多数のエンドプロジェクト(コンソールアプリ、Webサイト)で共有される中央の「コア」クラスが必要です。だから私はここに2つの質問があると思います:

a)このアプローチは正しいですかb)私の実装は正しいですか

これは非常に小さなクラスであることは知っていますが、最初から正しく理解したいと思います。

public static class Global {
        static IWindsorContainer _Container;
        static int ContainerInitalised = 0;
        static string ServicesFile;

        public static IWindsorContainer Container{
            get{
                if (Interlocked.CompareExchange(ref ContainerInitalised, 1, 0) == 0) {
                    Collection<IWindsorInstaller> installers = new Collection<IWindsorInstaller> {
                        { FromAssembly.InDirectory(new AssemblyFilter("Installers")) }
                    };
                    if (!String.IsNullOrWhiteSpace(ServicesFile)) {
                        installers.Add(Configuration.FromXmlFile(ServicesFile));
                    }
                    _Container = new WindsorContainer().Install(installers.ToArray());
                }
                return _Container;
            }
        }

        public static void Initialise(string servicesFile) {
            ServicesFile = servicesFile;
        }

    }
4

2 に答える 2

4

Davidによると、あなたのアイデアは、IoCコンテナを使用するための最悪の方法であるServiceLocatorソリューションに向かっています。

また、共通のインターフェイスでIoCコンテナを抽象化すると、特別なコンテナ機能が失われるため、お勧めできません。特に、リリースメソッドを公開しないインターフェイスは、RRRパターンに基づくwindosrなどの成熟したIoCコンテナを使用すると災害につながります。

正しいアプローチは、KrzysztofがNDCのプレゼンテーションで明確に説明しています。

  • MVC3の実装に従って、ファクトリを使用してIoCコンテナをアプリに接続します
  • できるだけ早く1つの解決を実行します。非Webアプリの場合は1つの解決、Webシナリオのリクエストごとに1つの解決を実行します。
  • 解決したものを常にリリースする
于 2012-07-06T17:12:34.477 に答える
0

「サービスロケーター」の実装に向けた一歩を踏み出すことで、少しクリーンアップできるかもしれません。(実際、これを正確に実行する共通のライブラリがあります。)

たとえば、インターフェイスの背後にあるIoCコンテナを抽象化し、現在の実装を提供する静的ファクトリを作成できます(ジェネリックGlobalクラスを置き換えて、よりターゲットを絞ることができます)。このようなもの:

public interface IoCContainer
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);
    T GetInstance<T>();
    T GetInstance<T>(string key);
    IEnumerable<T> GetAllInstances<T>();
}

public static class IoCContainerFactory
{
    private static IoCContainer current;

    public static IoCContainer Current
    {
        get
        {
            if (current == null)
                throw new DomainException("IoC Container Not Initialized.  This application must call a bootstrap method in an IoC implementation project.");
            return current;
        }
    }

    public static void Initialize(IoCContainer container)
    {
        current = container;
    }
}

次に、別のプロジェクトでインターフェイスを実装しIoCContainerます(StructureMapを使用し、Castleを使用します...多くのオプションがあります)。また、他のプロジェクトにはInitializer、コンテナー実装をブートストラップするクラスがあり(構成は実装ごとに異なるため)、最後のステップとして、この「グローバル」ファクトリを初期化します。

IoCContainerFactory.Initialize(new IoCContainerImplementation(ObjectFactory.Container));

(上記のコード行の場合、これIoCContainerImplementationは前述のインターフェイスの私の実装であり、ObjectFactoryStructureMapからのものであり、この前のコード行で構成/ブートストラップされただけです。)

もちろん、このアプローチでは、少しトレードオフがあります。共通のインターフェースの背後でIoCコンテナーを抽象化することにより、多くのIoCコンテナーの実装に共通することしかできません。私のニーズでは、依存関係を解決するためのメソッドを呼び出すだけです。ただし、クラス/プロパティを属性で装飾する(IoCコンテナーの選択にその機能がある場合)などの他のことは、その特定のコンテナーに緊密に結合するか、この実装を拡張して、何らかの方法でその機能を利用するカスタム属性を含める必要があります。

于 2012-07-06T14:02:26.087 に答える