[Autofac套件介紹-1] 淺談Autofac架構

本篇淺談Autofac架構,內容含括Autofac能做些甚麼、如何註冊Component和Service、如何透過Autofac取得實體類別,以及Autofac物件生命週期的控管。

淺談Autofac架構

Autofac是一套DI的framework,提供了豐富的使用情境,讓我們能透過依賴反轉(IOC)的程式設計原則,來降低程式碼的耦合度。

在Autofac的世界裡,我們稱實體化的物件為Component,而對外公開的介面稱為Service。所以在程式碼裡,各分層、物件之間都是透過介面(Service)做溝通,因此,未來如果需要抽換實體類別(Component)的邏輯就會變得非常單純、簡單。

Autofac的核心主要圍繞在三個層面

  • Registering Component  
  • Resolving Service  
  • Controlling Scopen and Lifetime  

Registering Component  

這個階段主要是在將Service和Component註冊對應關係,註冊的方式有很多種情境,包含最基本的指定型別註冊、甚至可以直接掃描Assembly根據裡面的內容來做大量註冊的動作。也許這樣敘述有點難理解,實際看一個例子會清楚些。

首先,先下載Autofac套件。

範例定義一個ICar介面(Service),只公開一個方法是Drive()。再來,定義一個MyCar類別(Component),實作ICar介面。

public interface ICar
{
    void Drive();
}

public class MyCar : ICar
{
    public void Drive()
    {
        Console.Write("Drive BMW");
    }
}

接下來,透過註冊,把ICar和MyCar關聯起來,下面的範例就是用類別的方式註冊,把MyCar(Component)註冊成ICar(Service)。

var builder = new ContainerBuilder();

builder.RegisterType<MyCar>().As<ICar>();

 

Resolving Service  

雖然已經註冊好ICar和MyCar之間的關係,但到目前為止仍然沒拿到實際的類別。繼續剛剛的例子,透過Autofac,我跟它說我需要一個實際的車子,而且必須是ICar的類型,請Autofac幫我處理,上面那句是白話,講技術一點就是請Autofac Resolving Service給我。Autofac會根據你所註冊的MyCar,將其實體化之後返回,所以我就可以得到一個MyCar的真實車子,然後執行Drive(),就會出現下方Console的內容。

var car = container.Resolve<ICar>();

car.Drive();

在Resolve動作裡,其實程式碼本身不知道返回的會是哪個實體類別,只知道它有實作ICar,所以,知道可以呼叫Drive()方法。這裡做到一個重要的程式設計原則=> 程式碼相依於介面,而非實作。

 

Controlling Scopen and Lifetime  

以前用new的方式建立物件,使用完畢後,即使不釋放(dispose)該物件,也會有記憶體回收機制來幫忙處理。但使用Autofac處理相依性後,原本new的動作將交由Autofac來處理,所以Autofac會主導此物件的生命週期,原本的記憶體回收機制就不會干涉,物件的釋放由Autofac全權處理。講白話就是,假如沒有釋放Autofac建立的物件,最終將會耗盡所有記憶體。

但也不必太擔心,Autofac本身有提供很多管理物件生命週期的方式,讓物件和記憶體的使用更有效率。以下就簡單介紹一下最基本的用法,使用Using搭配BeginLifetimeScope()來達到效果,在Using的結尾處,括號內的物件都會自動被釋放(dispose)。

using (var scope = container.BeginLifetimeScope())
{
    //注意resolve方法須由scope呼叫
    var car = scope.Resolve<ICar>();

    car.Drive();
}
scope呼叫Resolve生成物件後,當scope結束,便會自動釋放生成的物件。不建議直接用container.Resolve<ICar>()生成物件,否則你沒自己釋放物件,會造成記憶體爆掉的問題。

同場加映

本段落Demo一下相依於介面而非實作的威力。假如現在需求,我不想使用MyCar,而想使用YourCar來當作ICar的實作。只需兩個步驟,首先,當來得多一個YourCar的類別,這免不了。

public class YourCar : ICar
{
    public void Drive()
    {
        Console.Write("Drive LUXGEN");
    }
}

只需更改一個地方,將註冊MyCar的地方改成註冊YourCar。

//builder.RegisterType<MyCar>().As<ICar>();
builder.RegisterType<YourCar>().As<ICar>();

實際跑一下程式看看,如下所示,其他地方都無需更改,就達成需求。試想一下,假如系統有大量使用到ICar類別時,那省下的工將會非常多。

小結

本篇主要是要了解Autofac的整體圖像,以及DI所帶來的方便性,後續再深入研究Registering、Resolving、Component Lifetime會輕鬆很多。除此之外,Autofac也有很多整合性的擴充套件,如針對MVC的Autofac.MVC以及WebApi的Autofac.WebApi2,會讓我們更方便的使用Autofac的功能,這就留待後續探討吧。