Unity是微软在CodePlex上的一个开源项目,可用于依赖注入、控制反转,类似Spring,下面是使用示例:
1.先来定义几个接口、类
1 namespace UnityTest 2 { 3 public interface IRun 4 { 5 void Run(); 6 } 7 }
1 namespace UnityTest 2 { 3 public class Pet 4 { 5 public string Name { set; get; } 6 } 7 }
1 using System; 2 3 namespace UnityTest 4 { 5 public class Cat : Pet, IRun 6 { 7 public void Run() 8 { 9 Console.WriteLine("A cat is runing..."); 10 } 11 } 12 }
1 using System; 2 3 namespace UnityTest 4 { 5 public class Dog : Pet, IRun 6 { 7 public void Run() 8 { 9 Console.WriteLine("A dog is runing..."); 10 } 11 } 12 }
1 namespace UnityTest.Model 2 { 3 public class Person 4 { 5 IRun iRun; 6 7 public Person(IRun iRun) 8 { 9 this.iRun = iRun; 10 } 11 12 public void HiWeGo() 13 { 14 iRun.Run(); 15 } 16 } 17 }
2、创建对象实例
1 using System; 2 using System.Web.Script.Serialization; 3 using Microsoft.Practices.Unity; 4 5 namespace UnityTest 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 var container = new UnityContainer(); 12 container.RegisterType<IRun, Dog>(); //注册类型,并将IRun映射到Dog 13 var dog1 = container.Resolve<IRun>(); //创建一个IRun实例,实际上就是Dog 14 (dog1 as Dog).Name = "buddy"; 15 Console.WriteLine("a dog is born,his name is \"{0}\"", (dog1 as Dog).Name); //a dog is born,his name is "buddy" 16 Console.Read(); 17 } 18 } 19 }
3、使用标识符
当IRun同时有多个实例类要注入时,如果没有标识来区别,创建出来的实例“类型”就没办法显示指定。
1 var container = new UnityContainer(); 2 container.RegisterType<IRun, Dog>() 3 .RegisterType<IRun, Cat>(); 4 var run = container.Resolve<IRun>();//这里的run实例,是cat,还是dog ? 5 Console.Write(run.ToString());//UnityTest.Cat
1 var container = new UnityContainer(); 2 container.RegisterType<IRun, Dog>("dogType") 3 .RegisterType<IRun, Cat>("catType"); 4 var run = container.Resolve<IRun>("dogType");//明确指示,我要一个dog 5 Console.Write(run.ToString());//UnityTest.Dog
4、创建单例
1 var container = new UnityContainer(); 2 container.RegisterType<IRun, Dog>("dogTypeSingle", new ContainerControlledLifetimeManager())//dogTypeSingle为单例模式 3 .RegisterType<IRun, Dog>("dogType"); 4 5 var dog1 = container.Resolve<IRun>("dogTypeSingle"); 6 var dog2 = container.Resolve<IRun>("dogTypeSingle"); 7 8 Console.WriteLine(object.ReferenceEquals(dog1, dog2));//True 9 Console.WriteLine(dog1.GetHashCode() == dog2.GetHashCode());//True 说明dog1与dog2是同一个对象 10 11 var dog3 = container.Resolve<IRun>("dogType"); 12 var dog4 = container.Resolve<IRun>("dogType"); 13 Console.WriteLine(object.ReferenceEquals(dog3, dog4));//False 14 Console.WriteLine(dog3.GetHashCode() == dog4.GetHashCode());//False 说明dog3与dog4是不同的对象
5、依赖注入
构造器自动注入
1 var container = new UnityContainer(); 2 container.RegisterType<IRun, Dog>(); 3 var personWithDog = container.Resolve<Person>(); 4 personWithDog.HiWeGo();//A dog is runing...
构造器也可以结合标识符显示注入
1 var container = new UnityContainer(); 2 container.RegisterType<IRun, Dog>("dog") 3 .RegisterType<IRun, Cat>("cat") 4 .RegisterType<Person, Person>("PersonWithDog", new InjectionConstructor(container.Resolve<IRun>("dog"))) 5 .RegisterType<Person, Person>("PersonWithCat", new InjectionConstructor(container.Resolve<IRun>("cat"))); 6 7 var personWithDog = container.Resolve<Person>("PersonWithDog"); 8 personWithDog.HiWeGo();//A dog is runing... 9 var personWithCat = container.Resolve<Person>("PersonWithCat"); 10 personWithCat.HiWeGo();//A cat is runing... 11 Console.Read();
使用InjectionConstructor特性注入
为了演示[InjectionConstructor]特性,先改造一下Person类
1 using System.Collections.Generic; 2 using Microsoft.Practices.Unity; 3 namespace UnityTest 4 { 5 public class Person 6 { 7 private List<IRun> pets; 8 9 public Person() 10 { 11 pets = new List<IRun>(); 12 } 13 14 [InjectionConstructor] 15 public Person(IRun iRun):this() 16 { 17 pets.Add(iRun); 18 } 19 20 public Person(IRun iRun1,IRun iRun2):this() 21 { 22 pets.Add(iRun1); 23 pets.Add(iRun2); 24 } 25 26 27 public void HiWeGo() 28 { 29 foreach (var pet in pets) 30 { 31 pet.Run(); 32 } 33 } 34 } 35 }
测试一下:
1 var container = new UnityContainer(); 2 3 container.RegisterType<IRun, Dog>("dog") //注册一个带标识的dog类型 4 .RegisterType<IRun, Cat>("cat") //注册一个带标识的cat类型 5 .RegisterType<IRun, Dog>() //不指定标识,即默认IRun的实例为dog 6 .RegisterType<Person, Person>("PersonWithDogAndCat", 7 new InjectionConstructor( 8 container.Resolve<IRun>("dog"), 9 container.Resolve<IRun>("cat") 10 )//显示将二个参数的构造方法注册到容器中 11 ); 12 13 14 var person = container.Resolve<Person>();//自动调用有InjectionConstructor标记的构造方法 15 person.HiWeGo();//A dog is runing... 16 17 18 Console.WriteLine("---------------"); 19 20 var personWithDogAndCat = container.Resolve<Person>("PersonWithDogAndCat");//显式调用在容器中注册过的构造方法 21 personWithDogAndCat.HiWeGo(); 22 //A dog is runing... 23 //A cat is runing... 24 25 Console.Read();