設計哲學#

Simple Injector 是由本書共同作者 Steven van Deursen 所創建的 DI Container,其設計哲學強調安全性、正確性與簡潔性。與 Autofac 的兩階段 Builder Pattern 不同,Simple Injector 只有一個 Container 類別,在第一次解析後自動鎖定註冊。

var container = new Container();
container.Register<IProductService, ProductService>();
// 第一次 Resolve 後,註冊自動鎖定

Figure 14.1: Simple Injector 的使用模式:配置後,使用同一個容器實例解析元件

設計差異化特色#

Simple Injector 在幾個關鍵設計決策上與其他容器截然不同:

Ambient Scopes#

不同於 Autofac 需要明確從 Scope 解析物件,Simple Injector 使用 Ambient Scope 模式:

  • 直接從 Container 呼叫 GetInstance<T>()
  • 透過 Scope.Current 自動取得當前的 Scope
  • 這種設計防止了記憶體洩漏與並行問題,因為不需要傳遞 Scope 參考

Figure 14.3: Simple Injector 的 Scope 作為請求專屬的快取

獨立的集合註冊 API#

Simple Injector 將單一實作與集合實作的註冊明確分開

// 單一實作
container.Register<IProductService, ProductService>();

// 集合(多重實作)
container.Collection.Register<IEventHandler>(typeof(OrderHandler), typeof(PaymentHandler));

這避免了其他容器中「到底是解析單一物件還是集合?」的混淆。

不支援原始型別註冊#

Simple Injector 刻意不允許直接註冊原始型別(如 stringint)作為依賴,鼓勵開發者使用 Parameter Object 模式包裝設定值:

// 不允許直接注入 string
// 推薦做法:使用 Parameter Object
public class ConnectionSettings
{
    public string ConnectionString { get; }
}

內建驗證機制#

container.Verify();

Verify() 方法是 Simple Injector 的殺手級功能。它不只檢查所有註冊是否完整,還能偵測 Captive Dependencies(例如 Singleton 持有 Scoped 物件),這是其他容器通常無法發現的隱性錯誤。

Figure 14.4: Simple Injector 的完整使用模式:配置、驗證、解析

註冊方式#

Simple Injector 的註冊語法使用泛型型別約束,提供編譯期安全性:

// 泛型約束確保 ProductService 必須實作 IProductService
container.Register<IProductService, ProductService>();

如果 ProductService 沒有實作 IProductService,編譯器會直接報錯——這比 Autofac 的執行期錯誤安全得多。

Lifestyle 管理#

Simple Injector對應模式說明
Lifestyle.TransientTransient每次解析建立新實例(預設值
Lifestyle.SingletonSingleton整個容器只有一個實例
Lifestyle.ScopedScoped每個 Scope 內共享實例
container.Register<IProductService, ProductService>(Lifestyle.Singleton);

處理多重實作#

集合註冊#

集合支援 Assembly 掃描,方便 Auto-Registration:

container.Collection.Register<IEventHandler>(
    typeof(IEventHandler).Assembly);

Simple Injector 的集合是 Stream(延遲解析),每個元素在被列舉時才會被建立。這與 Autofac 預先解析所有實作的行為不同。

Decorator 支援(含條件式)#

// 裝飾所有 ICommandHandler
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(ValidationDecorator<>));

// 條件式裝飾:只裝飾特定實作
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(AuditDecorator<>),
    context => context.ImplementationType.Namespace.Contains("Admin"));

條件式 Decorator 支援 Predicate,可以根據被裝飾的實作類型來決定是否套用裝飾——這是 Simple Injector 獨特的強大功能。

Composite 支援#

Simple Injector 內建 Composite 支援,可以將集合中的所有實作自動組合:

container.RegisterComposite<IEventHandler, CompositeEventHandler>();
Simple Injector 重點回顧
  • 單一 Container 類別,首次解析後自動鎖定註冊
  • 泛型型別約束提供編譯期安全性(對比 Autofac 的執行期檢查)
  • Ambient Scope 設計避免記憶體洩漏與並行問題
  • 獨立的 Collection.Register API 明確區分單一與集合註冊
  • Verify() 方法能偵測 Captive Dependencies 等隱性錯誤
  • 條件式 Decorator 支援 Predicate,靈活控制裝飾邏輯
  • 集合為 Stream(延遲解析)
  • 本書共同作者 Steven van Deursen 為其創建者