代码改变世界

Unity Application 学习笔记1 --初识

2013-03-21 23:53  Shawn.Cheng  阅读(2103)  评论(1编辑  收藏  举报

上一篇文章中间简要的写了一个 关于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>

 

类和接口

View Code
 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,理解浅薄,请各位朋友见谅指正。

 

该睡了,晚安。