上一篇文章中间简要的写了一个 关于Autofac 东西。这两天看了一下关于Unity Application 的一些运用。
类似上一篇,写了几个相同的例子。
最开始时使用编码注入的方式。
代码如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Program p = new Program(); 6 //p.Test3(); 7 p.Test4(); 8 9 Console.Read(); 10 } 11 12 public void Test1() 13 { 14 UnityContainer container = new UnityContainer(); 15 container.RegisterType<ILog,PrintLoger>(); 16 container.RegisterInstance(Console.Out);//container.RegisterInstance<TextWriter>(Console.Out); 17 18 container.Resolve<ILog>().Create("this is test1"); 19 //将组件PrinterLoger注册到Ilog服务上,同时将Console.Out实例注册到TextWriter上 20 //请求Ilog服务的时候,会构造PrinterLoger组件的一个实例,使用参数Console.Out.构造成功。正常输出 21 container.Dispose(); 22 } 23 24 public void Test2() 25 { 26 UnityContainer container = new UnityContainer(); 27 container.RegisterType<PrintLoger>(); 28 container.RegisterInstance(Console.Out); 29 container.Resolve<PrintLoger>().Create("this is test2"); 30 container.Dispose(); 31 32 //可正常输出。理解应该和autofac相同,我们将PrinterLoger 注册到容器内 33 //同时将组件的实例注册到TextWriter上 34 //Resolve PrinterLoger时,会构造请求该服务的组件的一个实例,调用其构造函数,传入Console.out参数,正常运行输出 35 } 36 37 public void Test3() 38 { 39 UnityContainer container = new UnityContainer(); 40 container.RegisterType<Person>(); 41 Person p= container.Resolve<Person>(); 42 //本例子只是为了说明一个类可以注册到自己身上,并且Reslove出来 43 container.Dispose(); 44 } 45 46 public void Test4() 47 { 48 using (UnityContainer container=new UnityContainer()) 49 { 50 container.RegisterInstance<TextWriter>(Console.Out); 51 container.RegisterType<ILog, PrintLoger>(); 52 //RegisterType可以 有两个泛型参数,From,To,其中,To是继承与From的 53 //其实也就是将To组件注册到From服务上 54 //当请求Reslove一个PrintLoger实例的时候,这个地方貌似不同于AutoFac的处理 55 //能够使用该类去构造出一个实例(但前提是参数TextWriter可以Reslove出来) 56 57 container.Resolve<PrintLoger>().Create("this is test4");//此处跟autofac 不同,不注册PrintLoger 也可以Resolve出来 todo cjt!!!!! 58 } 59 } 60 61 62 }
类和接口
public interface ILog { void Create(string log, params object[] paramters); } public class PrintLoger : ILog { protected TextWriter TW { get; set; } public PrintLoger(TextWriter tw) { this.TW = tw; } public void Create(string log, params object[] paramters) { if (log == null) return; string Log = string.Format(log, paramters); TW.WriteLine(Log); } } public class Person { public string ID { get; set; } public string Name { get; set; } }
可以看出来,同Autofac的差别主要就在于Test4 上。在Autofac中,如果没有注册PrintLoger时,是无法Reslove 出一个实例的,而Unity Application 可以。
其他的,基本可以用相同的思维去理解。Register 将服务和组件 Map到一起(或者直接指定服务使用的组件实例)。
另外,Unity Application 还可以通过配置文件的方式,进行注入。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Program p = new Program(); 6 //p.Test1(); 7 p.Test2(); 8 p.Test3(); 9 10 Console.ReadKey(); 11 12 } 13 14 public void Test1() 15 { 16 IUnityContainer container = new UnityContainer().AddNewExtension<Interception>(); 17 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 18 //使用名称为Hello的Container,将文件中的配置读取初始化到Container中 19 section.Configure(container, "Hello"); 20 IHello hello = container.Resolve<IHello>(); 21 //由于在Hello Container中,我们将IHello map 到 HelloB ,其将使用HelloB 进行构造实例 22 //实际上,这个地方运行时,是会报错的,Container会无法Reslove Ilog,我们并没有在该Container中队Ilog进行映射 23 hello.SayHello(); 24 container.Dispose(); 25 } 26 27 public void Test2() 28 { 29 IUnityContainer container = new UnityContainer(); 30 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 31 //该例子比较好理解,我们在配置文件中的Log Container 中配置了Ilog map 到 ClassPrintLog中 32 //请求ILog服务的时候,将会构造PrintLog实例,PrintLog是无参构造,Reslove成功 33 section.Configure(container, "Log"); 34 container.Resolve<ILog>().Create("this is ilog"); 35 container.Dispose(); 36 } 37 38 public void Test3() 39 { 40 IUnityContainer container = new UnityContainer(); 41 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); 42 //在该节点的Container中,我们 将IHello map 到HelloA 将ILog map 到 PrintLog 43 //当请求Reslove IHello 时, 将会构造HelloA实例,然而发现HelloA 需要参数 ILog ,Container继续Reslove Ilog ,将会得到PrintLog实例 44 //如此,完成IHello hello=new HelloA(new PrintLog() ) 的构造 45 //Test1中和本例中都有一个不明白的地方,Unity 为什么会选中 含有参数的构造函数,而不使用无参的构造函数呢? Unity是如何选择构造函数的呢? 46 section.Configure(container, "SayHelloLog"); 47 container.Resolve<IHello>().SayHello(); 48 container.Dispose(); 49 } 50 51 }
配置文件
配置文件中 会在<typeAliases></typeAliases> 节点 为 需要注册的类增加别名。注意Type 是由 名空间.类名,程序集名 两部分构成的。
然后可以配置若干个Container,依据名字对其区分。
1 <?xml version="1.0"?> 2 <configuration> 3 <configSections> 4 <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/> 5 </configSections> 6 <unity> 7 <typeAliases> 8 <typeAlias alias="SayHello" type="ConAppUnityHelloWord.IHello,ConAppUnityHelloWord"></typeAlias> 9 <typeAlias alias="SayHelloA" type="ConAppUnityHelloWord.ClassA,ConAppUnityHelloWord"></typeAlias> 10 <typeAlias alias="SayHelloB" type="ConAppUnityHelloWord.ClassB,ConAppUnityHelloWord"></typeAlias> 11 <typeAlias alias="Log" type="ConAppUnityHelloWord.ILog,ConAppUnityHelloWord"></typeAlias> 12 <typeAlias alias="PrintLog" type="ConAppUnityHelloWord.PrintLog,ConAppUnityHelloWord"></typeAlias> 13 </typeAliases> 14 <containers> 15 <container name="Hello"> 16 <types> 17 <type type="SayHello" mapTo="SayHelloB"> 18 <!--<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, 19 Microsoft.Practices.Unity.Configuration"></typeConfig>--> 20 </type> 21 </types> 22 </container> 23 <container name="Log"> 24 <types> 25 <type type="Log" mapTo="PrintLog"></type> 26 </types> 27 </container> 28 <container name="SayHelloLog"> 29 <types> 30 <type type="SayHello" mapTo="SayHelloA"></type> 31 <type type="Log" mapTo="PrintLog"></type> 32 </types> 33 </container> 34 </containers> 35 </unity> 36 <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>
类和接口
1 interface IHello 2 { 3 4 void SayHello(); 5 } 6 7 public class ClassB:IHello 8 { 9 public void SayHello() 10 { 11 Console.WriteLine(this.GetType().Name); 12 } 13 14 public ClassB() 15 { 16 17 } 18 19 public ClassB(ILog log) 20 { 21 log.Create("say hellob"); 22 } 23 } 24 25 26 public class ClassA : IHello 27 { 28 public void SayHello() 29 { 30 Console.WriteLine(this.GetType().Name); 31 } 32 33 public ClassA() 34 { 35 36 } 37 38 public ClassA(ILog log) 39 { 40 log.Create("say helloa"); 41 } 42 } 43 44 public interface ILog 45 { 46 void Create(string log); 47 } 48 49 public class PrintLog : ILog 50 { 51 public void Create(string log) 52 { 53 Console.WriteLine("this is log "+log); 54 } 55 }
对于 使用配置文件进行注入 理解上和使用编码方式差不多。都是将 组件映射到服务上,然后Container读取这些映射,Reslove出组件的实例。
不过这里还有一些疑问,等过些阵子明了了,再来解决。如果有路过的朋友能指点一二,将不胜感激。
1. Autofac中如果不注册 PrintLog 就无法ReslovePrintLog ,而Unity Application 中却可以,默认构造出该类的一个实例。这个差别是确实这样?还是代码有问题?。如果确实有这个差别,那么 二者存在这样差异在框架上又是什么原因。
2.如何通过Unity 的配置文件,注册 一个实例呢?就像RegisterInstance一样。疑惑中。
3. 还需要看一下Unity对 对象生命周期的管理。
初学IOC,理解浅薄,请各位朋友见谅指正。
该睡了,晚安。