Unity学习笔记(一):StopLight QuickStart

曾几何时,从Spring中认识了IoC这个词语,但它并没有撩动我的心,原因很简单,我懵懂年代的程序连个静态Factory来创建实例都显得有点多余,Ioc更没有登场的必要。真正认识IoC也许是在使用Castle的时候,记得印象最深刻的一个情景是,我们团队当时的BS项目,开始设计时使用了一个第三方组件,后来需求变动了,这个第三方组件的功能却跟不上需求,我们不得不要换用一个新的组件,但是项目已经部署,客户要求更新后如果出问题能自行恢复到旧版本,当时想到一个笨拙的方法是,要求客户备份一下程序,然后出问题覆盖之就可以了,但是这样有个个问题,新开发模块和维护模块是同时进行部署的,怎能保证同一个模块中一部分使用新的程序,而一部分要恢复到旧程序中去呢,显然在旧办法中不重新编译就达不到这个要求,而其中即使有良好的版本控制,也是一两个文件Undo就能了事的,幸好这时Windsor跳进了我们的视线,使用它通过配置文件实现组件的自由设换,帮助我们轻松度过难关。这虽然不是一个应用IoC的正途例子,却在实际中帮了我们大忙^_^,要想正统的了解IoC,就要重温Martin Fowler大叔的经典文章《Inversion of Control Containers and the Dependency Injection pattern中文版
随着P&P团队发布Entlib 4.0 的蓝图,Unity慢慢映入我的眼帘,又是一个轻量级的IoC,现在终于发布了1.0版本,到底性能如何,让我们先看看附带的StopLight QuickStart

1.在代码中注册对象的映射
代码如下:

IUnityContainer container = new UnityContainer()
                    .RegisterType
<ILogger, TraceLogger>()
                    .RegisterType
<IStoplightTimer, RealTimeTimer>();

// 为容器注册默认注入实例
Application.Run(container.Resolve<StoplightForm>());

基本的流程是:创建注入容器 => 注册对象映射 => 调用对象时根据映射关系创建对象
在这个QuickStart中创建对像具体的流程是
StoplightForm  -》StoplightPresenter  -》Stoplight -》ILogger -》TraceLogger
          -》StoplightSchedule -》IStoplightTimer -》RealTimeTimer -》ILogger(有重复的话,会检查是否已经曾经实例化过,如果有,找出所使用实例化的策略去实例化或者不重新实例化(单件模式))
          
在要实例化接口的地方使用Dependency属性,如(这里使用属性来做关联处理,对调试造成一定的麻烦,使用Unity时可能会在这里跟踪代码丢失的问题,唯一解决的办法就是直接使用Unity的源码嵌套到项目中进行使用 ^_^)

[Dependency]
public ILogger Logger
{
 
get return logger; }
 
set { logger = value; }
}

具体在Unity里面的是实现是

public object Resolve(IBuilderContext context) // IBuilderContext : 包含要生成父对象的构建信息
{
 Guard.ArgumentNotNull(context, 
"context");
 NamedTypeBuildKey key 
= new NamedTypeBuildKey(type, name); 
 IBuilderContext recursiveContext 
= context.CloneForNewBuild(key, null);
 
 
// 根据注册关联的信息按照响应的实例策略一层一层实例化
 return recursiveContext.Strategies.ExecuteBuildUp(recursiveContext);
}

同一接口也可以注册多个实例
如添加一个实现类

internal class MakeFunLogger : ILogger
{
 
ILogger Members
}


注册代码改为

IUnityContainer container = new UnityContainer()
  .RegisterType
<ILogger, TraceLogger>()
  .RegisterType
<ILogger, MakeFunLogger>()
  .RegisterType
<IStoplightTimer, RealTimeTimer>();

大家也许和我有同样的疑问,这里同时为ILogger注册了两个实例,那么运行时到底是实例哪一个呢?答案是后注册的那个(这个印象中和windsor好像是相反的,呵呵)

2.在配置文件中注册对象的映射
1)添加Configuration相关应用
Microsoft.Practices.Unity.Configuration;     
System.Configuration

2)创建建App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

 
<configSections>
  
<!-- 
  使用编译好的Unity组件
  <section name="unity"
      type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,
                 Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  
-->

  
<!-- 
  直接使用Unity源码
  (ps:我习惯应用组件不表明Version,因为组件版本是在更新的,如果限死Version有时候很麻烦,当然了,原则上同一组件的接口是不变才行,^_^)
  
-->
  
<section name="unity"
      type
="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
                 Microsoft.Practices.Unity.Configuration"
 />
 
</configSections>

 
<unity>

  
<typeAliases>
   
<!-- 
   创建对象别名,不是必须的
   其type格式是:对像的全名,程序集名
   
-->
   
<typeAlias alias="ILogger"
     type
="StopLight.ServiceInterfaces.ILogger, StopLight" />
   
<typeAlias alias="IStoplightTimer"
     type
="StopLight.ServiceInterfaces.IStoplightTimer, StopLight" />

   
<typeAlias alias="TraceLogger"
     type
="StopLight.ServiceImplementations.TraceLogger, StopLight" />
   
<typeAlias alias="RealTimeTimer"
     type
="StopLight.ServiceImplementations.RealTimeTimer, StopLight" />

  
</typeAliases>

  
<containers>
   
<container name="containerOne">

    
<types>

     
<!--
     注册映射,这里使用默认的生命周期和实例策略,具体设置可以看文档 ^_^
     
-->
     
<type type="ILogger" mapTo="TraceLogger"/>
     
<type type="IStoplightTimer" mapTo="RealTimeTimer" />

    
</types>
   
</container>
  
</containers>
 
</unity>
</configuration>

3)修改注册代码

// 使用配置文件
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section
              
= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Containers[
"containerOne"].Configure(container);

这样就可以使用文件进行配置 ^_^ 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章