DI コンテナ Unity の利用(その3)

前回に引き続き DI コンテナ Unity の利用についてです。

前回は注入されるインスタンスの生存期間がコンテナと同一となる ContainerControlledLifetimeManager を設定したときの動作について記述したので、今回はコンテナの受け渡しと複数インスタンスの注入について記述します。

ちょっと無理やりですが、プログラムの構造を次のようにします。

  • IServiceA インターフェイスを実装する ServiceA クラスがある。
  • IServiceB インターフェイスを実装する ServiceB クラスがある。
  • IComplexAB インターフェイスを実装する ComplexAB クラスがある。
  • ComplexAB クラスは、IServiceA インターフェイスの実装クラスと IServiceB インターフェイスの実装クラスへの依存がある。
  • Sample1 クラスは Unity コンテナを受け取り、ComplexAB クラスを生成する。
  • Program クラスの Main メソッドで UnityContainer の生成と設定を行い、Sample クラスのインスタンスを生成する。

プロジェクトの作成、NuGet から Unity を導入までは前回と同様になります。

それでは、IServiceA インターフェイスから。

namespace HandOverIUnityContainer
{
    public interface IServiceA
    {
        void MethodA();
    }
}

次に IServiceB インターフェイスです。

namespace HandOverIUnityContainer
{
    public interface IServiceB
    {
        void MethodB();
    }
}

次に IComplexAB インターフェイスです。

namespace HandOverIUnityContainer
{
    public interface IComplexAB
    {
        void ExecuteComplexAB();
    }
}

次に ServiceA クラスです。

using System;

namespace HandOverIUnityContainer
{
    public class ServiceA : IServiceA
    {
        public void MethodA()
        {
            Console.WriteLine("Executing ServiceA.MethodA!");
        }
    }
}

次に ServiceB クラスです。

using System;

namespace HandOverIUnityContainer
{
    public class ServiceB : IServiceB
    {
        public void MethodB()
        {
            Console.WriteLine("Executing ServiceB.MethodB!");
        }
    }
}

次に ComplexAB クラスです。

namespace HandOverIUnityContainer
{
    public class ComplexAB : IComplexAB
    {
        public ComplexAB(IServiceA serviceA, IServiceB serviceB)
        {
            _serviceA = serviceA;
            _serviceB = serviceB;
        }

        private IServiceA _serviceA;
        private IServiceB _serviceB;

        public void ExecuteComplexAB()
        {
            _serviceA.MethodA();
            _serviceB.MethodB();
        }
    }
}

コンストラクタの引数に IServiceA と IServiceB の2つを受け取るようにしています。

次に Sample クラスです。

using Microsoft.Practices.Unity;

namespace HandOverIUnityContainer
{
    public class Sample
    {
        public Sample(IUnityContainer container)
        {
            _container = container;
        }

        private IUnityContainer _container;

        public void ExecuteMethodAB()
        {
            var complexAb = _container.Resolve<ComplexAB>();
            // IComplexAB インターフェイスで解決をする場合には、IComplexAB インターフェイスの解決方法を登録しておく必要がある
            //var complexAb = _container.Resolve<IComplexAB>();
            complexAb.ExecuteComplexAB();
        }
    }
}

コンストラクタの引数で IUnityContainer を受け取り、ExecuteMethodAB メソッドでコンテナの Resolve メソッドで ComplexAB クラスのインスタンスを受け取るようにしています。IComplexAB インターフェイスの注入を受け取る方はコメントアウトしてあり、こちらを利用する場合には、次に説明する Program クラスの方で IComplexAB インターフェイスの解決方法を設定しておく必要があります(コメントアウトしています)。

最後に Program クラスです。

using Microsoft.Practices.Unity;
using System;

namespace HandOverIUnityContainer
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var container = new UnityContainer())
            {
                container
                    .RegisterType<IServiceA, ServiceA>()
                    .RegisterType<IServiceB, ServiceB>()
                    //.RegisterType<IComplexAB, ComplexAB>(
                    //    new InjectionFactory(c => new ComplexAB(
                    //        container.Resolve<IServiceA>(),
                    //        container.Resolve<IServiceB>())))
                    ;

                var sample = new Sample(container);

                sample.ExecuteMethodAB();
            }

            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
    }
}

先ほど説明した IComplexAB インターフェイスの解決ルールの部分をコメントアウトしています。
Sample クラスのコンストラクタにインターフェイスの解決ルールを設定したコンテナを渡し、ExecuteMethodAB メソッドを呼び出しています。

このプログラムを実行したときのコンソール出力のスクリーンショットを示します。

HandOverIUnityContainer を実行したときのスクリーンショット

次回は、WPF の MVVM パターンでの Unity DI コンテナの利用についてです。


2 thoughts on “DI コンテナ Unity の利用(その3)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です