[Solution] DI原理解析及Castle、Unity框架使用


本節目錄

DI介紹

控制反轉(Inversion of Control,英文縮寫為IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題.

依賴注入(Dependency Injection,英文縮寫為DI)是一種設計模式.

其實本質都是指同一件事,強調的內容不一樣.IoC強調容器的作用,DI強調注入的作用.

通常IoC和DI可以理解為一個意思,只是指的對象不同.

 

DI基本原理

DI本質上是通過容器來反射創建實例.

 

1個簡單的類

    class Person
    {
        public void Say()
        {
            Console.WriteLine("Person's say method is Called");
        }
    }

 

 反射代碼(className:類的全限定名)

        private static object CreateInstance(Assembly assembly, string className)
        {
            var type = assembly.GetType(className);
            return type != null ? Activator.CreateInstance(type) : null;
        }

 

執行(XX為命名空間)

        static void Main(string[] args)
        {
            var obj = CreateInstance(Assembly.GetExecutingAssembly(), "XX.Person");
            var person = obj as Person;
            if (person != null)
            {
                person.Say();
            }
            Console.ReadKey();
        }

在上面能看到1個問題,一般情況下.既然使用DI,就不知道具體的注入對象.所以強調面向接口編程.

所以實際上一般先定義接口,再通過DI容器創建對象.

    interface IPerson
    {
        void Say();
    }
    class Person : IPerson
    {
        public void Say()
        {
            Console.WriteLine("Person's say method is Called");
        }
    }

執行

        static void Main(string[] args)
        {
            var obj = CreateInstance(Assembly.GetExecutingAssembly(), "Demo.Person");
            var person = obj as IPerson;
            if (person != null)
            {
                person.Say();
            }
            Console.ReadKey();
        }

 

DI框架

DI框架流行的有Castle Windsor,Unity...(Autofac Spring.Net已經聊過,不再演示)

在DI框架中,一般需要將對象注冊到容器中,然后從容器解析出來.

 

Castle

Install-Package Castle.Windsor

待注入類

  interface ITransient
    {
         
    }

    interface IPerson
    {
        void Say();
    }
    class Person : IPerson, ITransient
    {
        public void Say()
        {
            Console.WriteLine("Person's say method is Called");
        }
    }

 

注冊解析方式一

        static void Main(string[] args)
        {
            using (var container = new WindsorContainer())
            {
                container.Register(Component.For<Person, IPerson>());
                var person = container.Resolve<IPerson>();
                person.Say();
            }
            Console.ReadKey();
        }

注冊解析方式二

    public class AssmInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly()   //選擇Assembly
                .IncludeNonPublicTypes()                    //約束Type
                .BasedOn<ITransient>()                         //約束Type
                .WithService.DefaultInterfaces()            //匹配類型
                .LifestyleTransient());                     //注冊生命周期
        }
    }
        static void Main(string[] args)
        {
            using (var container = new WindsorContainer())
            {
                container.Install(new AssmInstaller());
                var person = container.Resolve<IPerson>();
                person.Say();
            }
            Console.ReadKey();
        }

構造函數注入

    class Task : ITransient
    {
        public IPerson Person { get; set; }
        public Task(IPerson person)
        {
            Person = person;
            Person.Say();
        }
    }
        static void Main(string[] args)
        {
            using (var container = new WindsorContainer())
            {
                container.Install(new AssmInstaller());
                container.Resolve<Task>();
            }
            Console.ReadKey();
        }

屬性注入

    class Task : ITransient
    {
        public IPerson Person { get; set; }
        public Task()
        {
        }
        public void Say()
        {
            Person.Say();
        }
    }
        static void Main(string[] args)
        {
            using (var container = new WindsorContainer())
            {
                container.Install(new AssmInstaller());
                container.Resolve<Task>().Say();
            }
            Console.ReadKey();
        }

MVC集成

Install-Package Castle.Windsor.Mvc

 

Application_Start注冊

        protected void Application_Start()
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            var container = new WindsorContainer()
                .Install(FromAssembly.This());
            var controllerFactory = new WindsorControllerFactory(container.Kernel);
            ControllerBuilder.Current.SetControllerFactory(controllerFactory);
        }

 

 

Installer注冊

    public class AssmInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly()
                .IncludeNonPublicTypes()
                .BasedOn<ITransient>()
                .WithService.DefaultInterfaces()
                .LifestyleTransient());
            container.Register(Classes.FromThisAssembly()
                .BasedOn<Controller>()
                .LifestyleTransient()
                );
        }
    }

這樣Castle Windsor就能接管解析Controller了.

 

Unity

Install-Package Unity

待注入類

    public interface IPerson
    {
        void Say();
    }
    public class Person : IPerson
    {
        public void Say()
        {
            Console.WriteLine("Person's say method is Called");
        }
    }

注冊解析一

        static void Main(string[] args)
        {
            using (var container = new UnityContainer())
            {
                container.RegisterType<IPerson, Person>(new TransientLifetimeManager());
                var person = container.Resolve<IPerson>();
                person.Say();
            }
            Console.ReadKey();
        }

注冊解析二

        static void Main(string[] args)
        {
            using (var container = new UnityContainer())
            {
                container.RegisterInstance<IPerson>(new Person());
                var person = container.Resolve<IPerson>();
                person.Say();
            }
            Console.ReadKey();
        }

構造函數注入

    class Task : ITask
    {
        public IPerson Person { get; set; }
        public Task(IPerson person)
        {
            Person = person;
            Person.Say();
        }
    }

    public interface ITask
    {

    }
        static void Main(string[] args)
        {
            using (var container = new UnityContainer())
            {
                container.RegisterInstance<IPerson>(new Person());
                container.RegisterType<ITask, Task>();
                container.Resolve<ITask>();
            }
            Console.ReadKey();
        }

屬性注入

    class Task : ITask
    {
        [Dependency]
        public IPerson Person { get; set; }
        public Task(IPerson person)
        {
            Person = person;
        }
        public void Say()
        {
            Person.Say();
        }
    }
        static void Main(string[] args)
        {
            using (var container = new UnityContainer())
            {
                container.RegisterInstance<IPerson>(new Person());
                container.RegisterType<ITask, Task>();
                var task = container.Resolve<ITask>();
                task.Say();
            }
            Console.ReadKey();
        }

MVC集成

Install-Package Unity.Mvc

 

Application_Start注冊

        protected void Application_Start()
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            var container = new UnityContainer();
            container.RegisterType<IPerson, Person>();
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }

這樣Unity就接管了Controller的創建


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM