1. 程式人生 > >【翻譯Autofac的幫助文檔】1.入門指南

【翻譯Autofac的幫助文檔】1.入門指南

tran 忘記 ref face 設計 一個表 uil 國際 article

【寫在前面】嘗試做完一件工作之外自我覺得有意義的一件事,那就從翻譯Autofac的幫助文檔吧。

入門指南

將Autofac集成你的應用程序的步驟通常很簡單,一般是:

  • 時刻以IOC(控制反轉)的思想來規劃你的應用程序
  • 在你的Porject中添加Autofac引用
  • 按照如下步驟設計應用程序的啟動環節
    • 創建一個ContainerBuilder
    • 向ContainerBuilder註冊組件
    • 通過ContainerBuilder的Build()方法獲得Container(後續需用到)
  • 在應用程序運行環節時,按如下步驟執行
    • 通過Container獲得一個lifetime scope
    • 通過lifetime scope解析出組件實例
    • 通過實例繼續執行

本篇將通過入門指南實現一個簡單的Console應用程序,一旦有了基礎,後續可以延伸集成WCF、ASP.NET等等。

規劃應用程序

先簡單解釋一下IOC(控制反轉)。
通常情況下,類A若需要類B的一些功能,則在類A中需要通過“new”操作來完成創建和使用功能,這樣在代碼層面就固定住了類A和類B之間的相互依賴關系。這樣的“依賴”,在後續的重構或修改時,影響面很大。
而IOC(控制反轉)的思維,則是取消,由類A來創建類B,變更為在執行期間,由IOC容器來根據需要和約定自動創建類B來給類A使用。

Martin Fowler有一篇著名的文章,解釋何謂IOC,可以點擊“鏈接”查看。

在本篇的示例中,我們將定義一個類,這個類可以輸出一些數據;但我們不想和Console綁定住,因為我們並不能確定在實際使用過程中Console是否真的可用。

我們通常可以這樣實現:

using System;
 
namespace DemoApp
{
  // 定義個輸出接口
  public interface IOutput
  {
    void Write(string content);
  }
 
  // 為接口實現Console方式的輸出
  public class ConsoleOutput : IOutput
  {
    public void Write(string content)
    {
      Console.WriteLine(content);
    }
  }
 
  // 定義一個書寫器接口
  public interface IDateWriter
  {
    void WriteDate();
  }
 
  // 實現書寫器接口,輸出當前日期,請註意,它依賴於IOutput接口
  // 在運行時,才能獲得具體的輸出形式
  public class TodayWriter : IDateWriter
  {
    private IOutput _output;
    public TodayWriter(IOutput output)
    {
      this._output = output;
    }
 
    public void WriteDate()
    {
      this._output.Write(DateTime.Today.ToShortDateString());
    }
  }
}

至此,我們已經有了IOC思維了。下一步,我們將通過Autofac來實現它。

添加Autofac引用

第一步,需要在項目中添加Autofac的引用。建議通過NuGet方式(如下圖),將會自動添加到項目中。

技術分享

Autofac,除了Core之外,還有很多擴展,例如和ASP.NET MVC集成等等。

截至目前為止,Autofac Core最新版本為4.6.0,對應.net framework 4.5.

應用程序啟動

在應用程序啟動環節,你需要創建一個ContainerBuilder來註冊組件。
一個組件,可以是一個表達式,一個.NET類型,又或者可以是一個或者多個帶依賴項的Service等等。

簡單來說,如下這個實現接口的.NET類,我們有兩種方式來定義它的類型。

public class SomeType : IService
{
}
  • 作為類型自身,那就是SomeType
  • 作為接口,那就是IService

如上的例子,組件就是SomeType,同時也是包括SomeType和IService的兩種形態的服務。

在Autofac,你可以按照如下方式向ContainerBuilder註冊組件。

// 創建builder.
var builder = new ContainerBuilder();
 
// 通常情況下,我們感興趣的是IService:
builder.RegisterType<SomeType>().As<IService>();
 
// 或者,也可以同時註冊IService和SomeType
builder.RegisterType<SomeType>().AsSelf().As<IService>();

對於我們的示例應用程序,我們需要註冊所有組件(類),並公開它們的服務(接口),這樣就可以很好地連接起來。

我們還需要保存Container,以便以後可以使用它來解析類型。

using System;
using Autofac;
 
namespace DemoApp
{
  public class Program
  {
    private static IContainer Container { get; set; }
 
    static void Main(string[] args)
    {
      var builder = new ContainerBuilder();
      builder.RegisterType<ConsoleOutput>().As<IOutput>();
      builder.RegisterType<TodayWriter>().As<IDateWriter>();
      Container = builder.Build();
 
      // WriteDate在執行時,Autofac將自動根據註冊的組件進行裝配並執行.
      WriteDate();
    }
  }
}

現在我們有一個Container,所有的組件都已註冊,並且它們正在公開適當的服務。讓我們利用它吧。

應用程序執行

在應用程序執行,你需要使用你註冊的組件時,是通過lifetime scope來解析出相應組件實例的。

Container本身也是一個lifetime scope,從技術角度來說,你可以從Container直接解析出組件,然而並不推薦這樣用。

解析一個組件時,將會根據所定義的實例範圍,創建一個對象的新實例。(解析一個組件大致相當於調用“new”實例化一個類。很簡單的一個類比。),某些組件可能有特殊的Dispose(如組件本身實現了IDisposable)- Autofac可以在lifetime scope終止時也會自動處理這些組件特殊的Dispose。

Container這個lifetime scope,在應用程序執行時會一直存在。所以,如果用Container來解析所有的組件的話,可以想象當應用程序終止時,Dispose將是多麽繁忙的景象(所有的組件等待被Dispose),同樣,因為直到最後一刻才會被Dispose,會更大幾率引發“內存不足”這個問題。

所以,推薦從Container創建一個新的lifetime scope來解析組件,在完成相關執行代碼後,lifetime scope連帶著組件即可被釋放。

(一旦你使用了Autofac integration libraries,創建和使用lifetime scope後就可以完全忘記它)

對於我們的示例應用程序,我們將創建一個lifetime scope,然後解析出writer這個組件,並執行“writedate”方法。

namespace DemoApp
{
  public class Program
  {
    private static IContainer Container { get; set; }
 
    static void Main(string[] args)
    {
      // ......
    }
 
    public static void WriteDate()
    {
      // 創建scope, 解析IDateWriter,
      // 使用它, 銷毀scope.
      using (var scope = Container.BeginLifetimeScope())
      {
        var writer = scope.Resolve<IDateWriter>();
        writer.WriteDate();
      }
    }
  }
}

現在運行程序…

  • “writedate”方法要求一個idatewriter。
  • autofac看到idatewriter映射到TodayWriter,開始創建一個todaywriter。
  • autofac看到todaywriter需要ioutput來完成構造。
  • autofac看到ioutput映射到consoleoutput,所以創建一個新的consoleoutput實例。
  • autofac采用新consoleoutput實例完成建設TodayWriter。
  • autofac返回完全構成TodayWriter,可以開始執行“writedate”了。

以後,如果你希望應用程序寫另一個日期的話,可以實現一個不同的idatewriter然後改變登記程序的啟動。你不需要改變其他的類。是的,這就是IOC(控制反轉)!

註意:一般來說,Service很大程度上被認為是一種反模式(看文章)。因此,在你的程序中人工創建scope並使用Container,這種方式不是最好的。使用“Autofac integration libraries”,你通常不需要像示例程序那樣人工創建scope。當然,你如何設計應用程序取決於你自己。

本篇結束。

後述:完整的英文版鏈接在此:http://autofac.readthedocs.io/en/latest/getting-started/index.html,有部分內容沒有翻譯,也有部分內容自我感覺翻譯的並不恰當。若你有意見和建議,可聯系我。

本博文屬作者原創,首發於www.boxfun.net,除非特別聲明,本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。

【翻譯Autofac的幫助文檔】1.入門指南