WebApi 插件式構建方案:IOC 容器初始化


一般來說,一個現代化的網站加載流程是這樣的:程序集加載后,我們會初始化 IOC 容器,以便於接下來解析對象用。

我們插件式的開發,這一步更為重要。這是因為在開發階段,這些程序集以及 IOC 配置都是分屬於多個解決方案的,在部署前很可能還沒有連調。如何在集成在一起后,保證起碼的可用性,是很關鍵的一個步驟。研究稍微深一點的同學,應該很清楚 WebApi 框架本身就集成了一個 IOC 框架用於對象的生成。我們要做的工作就是在此基礎上擴展,把我們要額外注入的東西添加進去。

IOC 容器選型:Unity

選用 Unity 無可厚非,公司一直在用並且也沒什么想換的意思。在第一篇文章里,@elder 說 MEF 不錯,但是大環境下,確實沒見過有人在用。包括微軟自家的 MVC 和 WebApi,基本思想都是實現 CommonServiceLocation。如果有企業級的應用在使用 MEF,不妨通過私信告訴我。我也想看看這個集成在 .Net 4 中的微軟親兒子,到底是騾子還是馬。

不管怎么說,多一種選擇總是沒錯的。至於其它的 IOC 框架,從對 CommonServiceLocation 做適配上來看,基本上都是大同小異,只是獲取類型注冊的方式有所不同而已。

這里我選用現成的 Unity.WebApi 組件將 WebApi 自身的 IOC 容器擴展到 Unity 中(反編譯后可以發現就兩個類,直接把代碼拷貝出來,貼到項目里也是可以的)。

容器注冊項加載約定

對於一個 IOC 容器來說,通過配置文件加載注冊項都是不可或缺的。連 Ninject 這種奇葩,都有第三方對其擴展了配置文件支持。在編程中,我個人特別討厭不想干的代碼侵入,所以一般我會把 IOC 的注入寫在配置文件中:一方面代碼干凈了,另一方面,一個簡單的配置修改,就可以不用重新編譯代碼了,這不就是 IOC 的本質嗎?

配置文件可以多次附加配置到一個 IOC 容器實例上很必要,這樣我就可以連續把多個配置文件的注冊項添加到一個實例上。事實上,IOC 容器的實例,全局有且只有一個的時候才有用。回到咱們的 Unity 上面,很不幸的是,Unity 支持這個要求,呵呵。

額外的,為了項目整體上一致,我為 Unity 的配置文件約定:

  • Unity 配置文件名稱為 unity.config
  • 存放路徑為:相對當前程序集所在目錄的 Configuration\unity.config,這樣只需要調整生成時總是復制就可以了。

注:這里如果你想靈活一些,可以在上一節的配置文件中添加你的 Unity 配置文件路徑設置信息。

部分源代碼:自然語義

額外的,在 Global 中需要用 Unity.WebApi 把擴展點掛接上。下面是 IOC 加載各個模塊配置的事情代碼:

public interface IContainerConfiguration
{
  object Config(object container);
}

public class DefaultContainerConfiguration : IContainerConfiguration
{
    public object Config(object container)
    {
        var data = new List<string>();

        data.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configuration\\unity.config"));

        foreach(var item in DynamicModule.Instance.Modules)
        {
            data.Add(Path.Combine(item.BaseDirectory, "Configuration\\unity.config"));
        }
    }
}

補充:程序集加載

上一節寫完以后,有人私信問我加載順序的問題。在這里補充一下,程序集的加載和順序是無關的:我可以先加載接口的實現程序集,再加載接口程序集。但是還有一些需要注意的地方:

  • 程序集加載時,首先加載的程序集 B 如果引用了后續加載的程序集 A,加載不會產生錯誤。
  • 后續被引用的程序集 A 被加載后,先前加載的程序集 B 中的類型就可以正常訪問了。
  • 在后續程序集 A 加載之前,如果有使用 B 中的程序集,就會提示出錯;后續程序集 A 加載后,這個錯誤仍將繼續存在,且一直存在。

所有正確的做法是:程序集加載可以無序進行,但是一定要加載全部程序集后,再進行后續操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM