Unity 是Microsoft推出的IOC Container 套件,使用上除了在程式碼裡進行型別的註冊之外,也可以使用設定檔的方式來設定要註冊的型別,透過設定檔的好處是程式碼不用重新譯就可以抽換實作類別,以ASP.NET Web Sie 來說,會在web.config裡進行設定,多數情況下抽象型別會與實作類別的組件一樣置放在bin的目錄裡,然而在某些特殊或是不得不的情況下,組件會是註冊在GAC(assembly)裡,此時Unity的設定檔就必須稍微注意一下囉。
情境:
因特殊需求或是不得不的原因,定義的抽象型別組件是註冊在GAC(assembly)裡,並不存在於web site的bin目錄,在這種情況下如果Unity 設定檔的順序位置擺放不正確,或是未明確指定assembly時,將會造成以下錯誤情況。
解決方式:
一般情況下,我們在Web.config裡所看到的Unity設定會是如下,其中Type是我們所定義的抽象型別,而mapTo則是指定實作的類別。
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register
type="Mylibrary.Framework.ILeaveCustomize"
mapTo="ACus.Customize.LeaveRequest, ACus.Customize" />
</container>
</unity>
而在程式裡面會撰寫IUnityContainer container = new UnityContainer().LoadConfiguration()進行設定檔的載入,多數情況下這樣的定義是不會有問題的,除非把type及mapTo的型別命名空間給弄錯了,才會造成有無法找到型別的例外錯誤發生。
但如果我們的抽象型別組件是在GAC(assembly)裡,那麼以上的設定就會出現無法找到型別的例外錯誤發生,但原因卻不是型別命名空間給錯所引起的,此時一定會覺得奇怪,明明型別命名空間跟組件都沒錯,甚至改成不透過設定檔,直接在程式裡進行註冊跟解析都會正常運作,但透過設定檔卻會出錯,主要原因是因為組件還沒有被參考被進來,所以會解析不到型別。
解決方式不難,主要要注意二個地方,首先由於抽象型別的組件是在GAC(assembly)裡,所以設定檔的部份要加一段指定assembly的部份,如下所示,如果不知道assembly的版本跟PublicKeyToken資訊,請找一下你的web.config檔案,在add assembly的設定區段就知道了。
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="Mylibrary.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxx" />
<container>
<register
type="Mylibrary.Framework.ILeaveCustomize"
mapTo="ACus.Customize.LeaveRequest, ACus.Customize" />
</container>
</unity>
除此之外,整個Unity的設定區段必須移到Web.config 的 <add assembly=.......>之後,此時組件才有被真正參考進來,由於Web.config 可能設定的很複雜,為避免放的位置錯誤,我的建議是可以把Unity的設定區段放到整個Web.config 的底部,也就是configuration結束之前就可以了。
總結:
By No.18