雖然 Autofac 的確不是Orchard的公共API的一部分,它派上用場,當你需要自定義你的一些類的創建和管理的autofac,當你需要定制你的一些類是由Autofac創建和管理。
一般而言,當您編寫自己的注射類,您將采取下列步驟:
- 1、定義一個接口,來源於IDependency;
- 2、定義一個類,實現接口;
然而,在某些情況下,你可能想要注入具體的類直接進入你的構造函數,而不是一個接口。一個例子是當你在實現命令模式時,你通常會有多個類,最終實現一些ICommand接口,接下來,考慮使用一個控制器,依賴於一些命令,例如:SaveCustomerCommand。一個解決方案是為每個命令創建一個特定的接口。這將是完美的(甚至這些命令對於單元測試也是完美的)。但是我想由於某種原因你不想寫這些接口。但是你怎么能注入一個UpdateCustomerCommand或SaveCustomerCommand 呢?
為了這樣做,我們寫一個類繼承自Autofac.Module並且重載它的Load方法,Load方法接受一個類型為ContainerBuilder的參數,這就是所有我們需要注冊新的類型。
讓我們看一個例子:
首先,讓我們定義一個ICommand接口和兩個實現類:SaveCustomerCommand和CreateOrderCommand:
Commands/ICommand.cs:
public interface ICommand { void Execute(); }
Commands/SaveCustomerCommand.cs:
public class SaveCustomerCommand : ICommand { private readonly ICommerceServices _services; // Commands support DI just like any other class public SaveCustomerCommand(ICommerceServices services) { _services = services; } public void Execute() { // perform some action here, e.g. create a new customer or update an existing one } }
Commands/CreateOrderCommand.cs:
public class CreateOrderCommand : ICommand { private readonly ICommerceServices _services; // Commands support DI just like any other class public CreateOrderCommand(ICommerceServices services) { _services = services; } public void Execute() { // perform some action here, e.g. create a new order } }
這個ICommerceService接口只是一個接口示例它沒有任何成員:
Services/ICommerceServices.cs:
public interface ICommerceServices {}
接下來,我們將定義兩個控制器,一個控制器需要依賴SaveCustomerCommand而其他需要依賴CreateOrderCommand。
Controllers/CustomerController.cs:
public class CustomerController : Controller { private readonly SaveCustomerCommand _saveCommand; // Inject a SaveCustomerCommand public CustomerController(SaveCustomerCommand saveCommand) { _saveCommand = saveCommand; } public ActionResult CreateCustomer() { _saveCommand.Execute(); return Content("Customer created"); } }
Controllers/OrderController.cs:
using System.Web.Mvc; using Orchard.Docs.Misc.Commands; namespace Orchard.Docs.Misc.Controllers { public class OrderController : Controller { private readonly CreateOrderCommand _createOrderCommand; // Inject a CreateOrderCommand public OrderController(CreateOrderCommand createOrderCommand) { _createOrderCommand = createOrderCommand; } public ActionResult CreateOrder() { _createOrderCommand.Execute(); return Content("Order created"); } } }
現在,為了讓這個工作,我們需要告訴Autofac如何給我們這些命令類型。創建另一個類,它來繼承自Autofac.Module(注意:需要添加 Autofac程序集的引用。)
ModuleBuilders/CommandsModule.cs:
using Autofac; using Autofac.Features.ResolveAnything; public class CommandsModule : Module { protected override void Load(ContainerBuilder builder) { // Configure Autofac to create a new instance of any type that implements ICommand when such type is requested builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t => t.IsAssignableTo<ICommand>())); } }
基本上,我們為注冊了一個類型:“AnyConcreteTypeNotAlreadyRegisteredSource”,傳遞一個謂詞的類型注冊。我們通知他注冊所有的類型,通過利用Autofac的擴展方法IsAssignableTo < T >實現ICommand。
效果:每當我們請求一個實現了ICommand類型,Autofac將為我們提供該類型的示例。
原文地址:http://skywalkersoftwaredevelopment.net/orchard-development/api/autofac-module