[IoC容器Unity]第4回:パラダイム(デカップ依存注入機構)を使用する.


出典:http://www.cnblogs.com/qqlin/archive/2012/10/18/2720830.html
1.引用
前の章ではUnityの基本的な使用を紹介しました.主にプログラムとプロファイルに分けられています.リンクを参照してください.
  • [IoC容器Unity]第1回:Unityプレビュー
  • [IoC容器ユニティ]第二回:ライフサイクル
  • [IoC容器Unity]第3回:依存注入
  • 今回は終了編として、プロジェクトでユニティをどう使うかを紹介します.   
    2.パラダイム
    Unityは広く応用されています.多くのオープンソース種目にユニティの姿が見られます.マイクロソフトのオープンソースプロジェクトのニュースを持ってシステムを発表します. Kigg 例えば、Kiggの依存注入はユニティに使われています.ダウンロードできます.KiggはMVCアプリケーションの推奨例であり、IoC容器への依存注入を紹介します.この容器はKigg.Cooreプロジェクト、Infraastructureディレクトリの下にあるIOCディレクトリです.このカタログの下には4つの種類があります.以下の図の通りです.
    まず見てください IDependencyResolaver インターフェース宣言
        public interface IDependencyResolver : IDisposable
        {        /// 
            ///    T            /// 
            /// 
            /// 
            void Register(T instance);        /// 
            ///    
            /// 
            /// 
            /// 
            void Inject(T existing);        /// 
            ///           /// 
            /// 
            /// 
            /// 
            T Resolve(Type type);
    
            T Resolve(Type type, string name);
    
            T Resolve();
    
            T Resolve(string name);
    
            IEnumerable ResolveAll();
        }
    このインターフェースの定義を見て、私達はすぐにユニティの中のIユニティContiner容器インターフェースを思い付きます.なぜ直接IUnityContinerを使用しないで、似たようなインターフェースIDependencyResolaverを定義しますか?  Kiggを見ることができるIDependencyResolaverはコア層のKigg.coreがベースアーキテクチャ層に相当すると定義されていますが、この層はコアライブラリであり、他の層はそれを参照して、Kiggはアダプタモードを適用してパッケージ化します.ユニティとスピニング.netのような他の外部インターフェースを使用するシステムの依存注入方法が統一されていません.パッケージ化を行うには、まず公共インターフェースを定義し、ユニティと他のコンポーネントを利用してそれを実現することができます.これがIDependencyResolaverの由来です.
     
    KiggはUnityを利用してIDependencyResolaverインターフェースを実現しました.もちろん他の依存注入容器でも実現できます.UnityDependencyResolaverの実現を見てみます.
    public class UnityDependencyResolver : DisposableResource, IDependencyResolver
        {        //    
            private readonly IUnityContainer _container;
    
            [DebuggerStepThrough]        public UnityDependencyResolver() : this(new UnityContainer())
            {
                UnityConfigurationSection configuration = (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
                configuration.Containers.Default.Configure(_container);
            }
    
            [DebuggerStepThrough]        public UnityDependencyResolver(IUnityContainer container)
            {
                Check.Argument.IsNotNull(container, "container");
    
                _container = container;
            }
    
            [DebuggerStepThrough]        public void Register(T instance)
            {
                Check.Argument.IsNotNull(instance, "instance");            //                _container.RegisterInstance(instance);
            }
    
            [DebuggerStepThrough]        public void Inject(T existing)
            {
                Check.Argument.IsNotNull(existing, "existing");            //                _container.BuildUp(existing);
            }
    
            [DebuggerStepThrough]        public T Resolve(Type type)
            {
                Check.Argument.IsNotNull(type, "type");            //  
                return (T) _container.Resolve(type);
            }
    
            [DebuggerStepThrough]        public T Resolve(Type type, string name)
            {
                Check.Argument.IsNotNull(type, "type");
                Check.Argument.IsNotEmpty(name, "name");            return (T) _container.Resolve(type, name);
            }
    
            [DebuggerStepThrough]        public T Resolve()
            {            return _container.Resolve();
            }
    
            [DebuggerStepThrough]        public T Resolve(string name)
            {
                Check.Argument.IsNotEmpty(name, "name");            return _container.Resolve(name);
            }
    
            [DebuggerStepThrough]        public IEnumerable ResolveAll()
            {            //       
                IEnumerable namedInstances = _container.ResolveAll();
                T unnamedInstance = default(T);            try
                {
                    unnamedInstance = _container.Resolve();
                }            catch (ResolutionFailedException)
                {                //When default instance is missing            }            if (Equals(unnamedInstance, default(T)))
                {                return namedInstances;
                }            return new ReadOnlyCollection(new List(namedInstances) { unnamedInstance });
            }
    
            [DebuggerStepThrough]        protected override void Dispose(bool disposing)
            {            if (disposing)
                {
                    _container.Dispose();
                }            base.Dispose(disposing);
            }
        }
    UnityDependencyResoloverのデフォルトのコンストラクタは、プロファイルをロードしてIUnity Continerを初期化することができます.また、プログラミングすることもできます.実現方式ではユニティ・コンタイナーやユニティ・コンタイナーを継承しておらず、ユニティ・コンタイナーとの結合関係がより柔軟になります.これは対象のAdapterモードです.コンビネーションモードです.他のIoC容器があれば、Windows/Structure Map/Spring.Netなど、IDependencyResoverインターフェースを実現すればいいです.
     
    使う時は、実用化に対応するIDependencyResolaverオブジェクトだけが必要です.KiggではIDependencyResoloverオブジェクトの作成をよりよく制御するために、工場法を利用して作成しました.まず工場インターフェースIDependencyResoluverFactoryを見てください.
        public interface IDependencyResolverFactory
        {        /// 
            ///   IDependencyResolver           /// 
            ///         IDependencyResolver CreateInstance();
        }
    定義を参照してください.CreateInstanceはIDependencyResolaverオブジェクトを作成する方法です.この工場を実現できます.直接new Unity DependencyResoloverを作成できます.Kiggではプロファイル方式を利用してDependencyReslactoryを見てください.
        public class DependencyResolverFactory : IDependencyResolverFactory
        {        private readonly Type _resolverType;        public DependencyResolverFactory(string resolverTypeName)
            {
                Check.Argument.IsNotEmpty(resolverTypeName, "resolverTypeName");            //GetType(  ,      ,    )
                _resolverType = Type.GetType(resolverTypeName, true, true);
            }        public DependencyResolverFactory() : this(new ConfigurationManagerWrapper().AppSettings["dependencyResolverTypeName"])
            {
            }        public IDependencyResolver CreateInstance()
            {            //          
                return Activator.CreateInstance(_resolverType) as IDependencyResolver;
            }
        }
    デフォルトのコンストラクタはプロファイルdependencyResoverType Nameノードを読み取り、反射Activator.reat Instanceを利用して作成し、dependencyResoverType Nameノード定義を見てください.Kigg.Webプロジェクトのプロファイルでは、以下の通りです.
        
            
            
        
    他のIoC容器が実装されている場合は、設定ファイルを変更すればいいです.
     
    使用時に工場の方法を呼び出してIDependencyResoloverオブジェクトを作成します.使用するたびに工場を利用して作成します.IDependencyResolaverの中の方法は全部実例的な方法に違いないです.使用も不便です.Kiggは私達のために静的な方法にカプセル化します.IoC類の声明を見てください.
     public static class IoC
        {        //   
            private static IDependencyResolver _resolver;        /// 
            ///    ,              /// 
            ///         [DebuggerStepThrough]        public static void InitializeWith(IDependencyResolverFactory factory)
            {
                Check.Argument.IsNotNull(factory, "factory");
    
                _resolver = factory.CreateInstance();
            }        /// 
            ///             /// 
            /// 
            ///         [DebuggerStepThrough]        public static void Register(T instance)
            {
                Check.Argument.IsNotNull(instance, "instance");
    
                _resolver.Register(instance);
            }        /// 
            ///             /// 
            /// 
            ///         [DebuggerStepThrough]        public static void Inject(T existing)
            {
                Check.Argument.IsNotNull(existing, "existing");
    
                _resolver.Inject(existing);
            }        /// 
            ///             /// 
            /// 
            /// 
            ///         [DebuggerStepThrough]        public static T Resolve(Type type)
            {
                Check.Argument.IsNotNull(type, "type");            return _resolver.Resolve(type);
            }        /// 
            ///             /// 
            /// 
            /// 
            /// 
            ///         [DebuggerStepThrough]        public static T Resolve(Type type, string name)
            {
                Check.Argument.IsNotNull(type, "type");
                Check.Argument.IsNotEmpty(name, "name");            return _resolver.Resolve(type, name);
            }        /// 
            ///             /// 
            /// 
            ///         [DebuggerStepThrough]        public static T Resolve()
            {            return _resolver.Resolve();
            }        /// 
            ///             /// 
            /// 
            /// 
            ///         [DebuggerStepThrough]        public static T Resolve(string name)
            {
                Check.Argument.IsNotEmpty(name, "name");            return _resolver.Resolve(name);
            }        /// 
            ///             /// 
            /// 
            ///         [DebuggerStepThrough]        public static IEnumerable ResolveAll()
            {            return _resolver.ResolveAll();
            }        /// 
            ///           ///         [DebuggerStepThrough]        public static void Reset()
            {            if (_resolver != null)
                {
                    _resolver.Dispose();
                }
            }
        }
    IDependencyResolaverはIoCのプライベートスタティックメンバーです.プライベートはどのようにオブジェクトを作成しますか?IoCはInitializwith(IDependencyResoverFactory factory)があります.工場方法を利用して作成します.これからはIoCという種類を使えばいいです.IoC静的クラスは、DependencyResoverFactoryのような具体的な実装に依存しない依存性を考慮して、IDependencyResoloverオブジェクトを作成するための外部アクセスのための方法を提供します.
    IDependencyResolaverはいつ作成されますか?コンストラクタの作成が実現されていないので、必ずIoCのInitializwithメソッドを呼び出します.私たちは参照を見つけることができます.ブートガイドBootstraper類は以下の通りです.
        public static class Bootstrapper
        {        static Bootstrapper()
            {            try
                {
                    IoC.InitializeWith(new DependencyResolverFactory()); 
                }            catch (ArgumentException)
                {                // Config file is Missing            }
            }        public static void Run()
            {
                IoC.ResolveAll().ForEach(t => t.Execute());
            }
        }
    BootstrapherのコンストラクターでIDependencyResolaverを作成しました.Bootstrapherを初めて使う時に作成します.それは必ずBootstraperがIoCの前に使います.IoCクラスを使う時は間違いがあります.心配しないでください.Bootstraperは早く使います.ブートクラスなので、参照してください.Kigg.Web下のGlobal.asaxファイルで見つけられます.以下のように声明します.
        public class GlobalApplication : HttpApplication
        {        public static void OnStart()
            {
                Bootstrapper.Run();
                Log.Info("Application Started");
            }        public static void OnEnd()
            {
                Log.Warning("Application Ended");
                IoC.Reset();
            }        protected void Application_Start()
            {
                OnStart();
            }        protected void Application_End()
            {
                OnEnd();
            }
        }
    もともとApplicationにいました.Startでは、プログラムを起動する時に使います.はい、後はそのままIocを使って依存対象を作りましょう.newは不要です.Unityの配置ファイルは全部Web.configの中にあります.紹介しません.Kiggの依存容器は紹介しました.
    3.結び目
    私達はIoC容器が欲しいなら、拡張しやすく使いやすいです.Kiggを参照してください.
    IUnityContiner容器はN個のオブジェクトを声明してもいいです.そうすると管理が難しくなります.一度だけ作成して、スタティックメンバーを使ってもいいです.
    心配しないでください.IUnityContiner容器には多すぎるオブジェクト関係が登録されていて、解析性能に影響を与えます.IUnityContinerには多くの辞書が維持されています.つまり100個登録するのは登録100 Wのマッピングと同じです.
    IUnityContinerは、プログラムマッピングとプロファイルマッピングにより、プロファイルマッピングを推奨することができます.