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);

這樣就可以使用文件進行配置 ^_^ 

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