控制反轉上層不依賴下層,而是依賴第三方依賴注入容器
上次的SimpleFactory就可以看做是第三方容器。學生student依賴SimpleFactory 而不直接依賴細節(Honor)
我們常用的第三方容器就是Unity,在VS中通過NuGet引入Unity的Dll,改造我們的Main方法
static void Main(string[] args) { { BasePhone honor = SimpleFactory.CreatePhone(); IPlayPhone student = SimpleFactory.CreateStudent(); student.PlayPhone(honor); IUnityContainer unityContainer = new UnityContainer(); unityContainer.RegisterType<IPlayPhone, Student>(); var studentUnity = unityContainer.Resolve<IPlayPhone>(); studentUnity.PlayPhone(honor); //Honor honor = new Honor(); //Student student = new Student(); //student.PlayPhone(honor); //student.PlayPhone(lumiaPhone); //student.PlayApplePhone(applePhone); //student.PlayGalaxy(galaxy); //student.PlayHonor(honor); } Console.ReadKey(); }
再將代碼改造下增加IPerson,Iiphone,IGame
public interface IPerson { Iiphone Iphone { get; set; } IGame Game { get; set; } } public class Student: BasePerson, IPerson { [Dependency] public Iiphone Iphone { get; set; } [Dependency] public IGame Game { get; set; } } public class Teacher: BasePerson, IPerson { [Dependency] public Iiphone Iphone { get; set; } [Dependency] public IGame Game { get; set; } }
public interface Iiphone { void UsePhone(); } public class Galaxy:BasePhone, Iiphone { public override void System() { Console.WriteLine("ANDROID"); } public void UsePhone() { Console.WriteLine("Galaxy"); } }
public interface IGame { void Game(); } public class SgsGame:IGame { public void Game() { Console.WriteLine("play 三國殺Game"); } } public class LolGame:IGame { public void Game() { Console.WriteLine("Play LoLGame"); } } static void Main(string[] args) { { IUnityContainer unityContainer = new UnityContainer(); unityContainer.RegisterType<IPerson, Teacher>(); unityContainer.RegisterType<Iiphone, Galaxy>(); unityContainer.RegisterType<IGame, SgsGame>(); var studentUnity = unityContainer.Resolve<IPerson>(); studentUnity.Iphone.UsePhone(); studentUnity.Game.Game(); }
這裏用的是依賴注入中的屬性注入,屬性注入在構造函數注入之後執行,而且需要增加[Dependency]這個特性,並且需要添加using Microsoft.Practices.Unity;的引用,所以大部分時候都用構造函數注入更方便, 還有方法注入項目中用的很少,在方法上加[InjectionMethod]特性
unity提供更靈活的用配置文件註冊的方法 在項目配置文件增加
<configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections> <unity> <containers> <container name="defaultContainer"> <register type="Abstract.IPerson,Abstract" mapTo="Abstract.Teacher, Abstract"/> <register type="Abstract.Iiphone,Abstract" mapTo="Abstract.Galaxy, Abstract"/> <register type="Abstract.IGame,Abstract" mapTo="Abstract.SgsGame, Abstract"/> </container> </containers> </unity>
則Main函數修改
static void Main(string[] args) { { IUnityContainer unityContainer = new UnityContainer(); UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName); configuration.Configure(unityContainer, "defaultContainer"); var studentUnity = unityContainer.Resolve<IPerson>(); studentUnity.OutputIdentity(); studentUnity.Iphone.UsePhone(); studentUnity.Game.Game(); } Console.ReadKey(); }