虽然 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