2

我阅读了另一个stackoverflow用户提出的以下文章.NET Junkie - Meanwhile... on the command side of my architecture,该用户概述了命令模式,并提供了如何在文章结尾使用DI的策略。使用依赖注入MVC​​ 3控制器的命令模式

这非常有帮助,但我错过了一件事,比方说我创建了一个名为CheckoutCustomerCommandHandler的新类。

现在,我们假设我需要通过构造函数将此命令和MoveCustomerCommandHandler注入控制器,无论出于何种原因。这是如何影响DI容器设置和构造函数的?

在核心,它们都实现相同的接口。看起来这会导致DI容器的查找问题。在文章例子,这里是他们的进样器设置:

public interface ICommandHandler<TCommand> 
{ 
    void Handle(TCommand command); 
} 

// Exactly the same as before, but now with the interface. 
public class MoveCustomerCommandHandler 
: ICommandHandler<MoveCustomerCommand> 
{ 
    private readonly UnitOfWork db; 

    public MoveCustomerCommandHandler(UnitOfWork db, 
    [Other dependencies here]) 
    { 
     this.db = db; 
    } 

    public void Handle(MoveCustomerCommand command) 
    { 
     // TODO: Logic here 
    } 
} 

// Again, same implementation as before, but now we depend 
// upon the ICommandHandler abstraction. 
public class CustomerController : Controller 
{ 
    private ICommandHandler<MoveCustomerCommand> handler; 

    public CustomerController(
    ICommandHandler<MoveCustomerCommand> handler) 
    { 
     this.handler = handler; 
    } 

    public void MoveCustomer(int customerId, 
     Address newAddress) 
    { 
     var command = new MoveCustomerCommand 
     { 
      CustomerId = customerId, 
      NewAddress = newAddress 
     }; 

     this.handler.Handle(command); 
    } 
} 

using SimpleInjector; 
using SimpleInjector.Extensions; 

var container = new Container(); 

// Go look in all assemblies and register all implementations 
// of ICommandHandler<T> by their closed interface: 
container.RegisterManyForOpenGeneric(
    typeof(ICommandHandler<>), 
    AppDomain.CurrentDomain.GetAssemblies()); 

// Decorate each returned ICommandHandler<T> object with 
// a TransactionCommandHandlerDecorator<T>. 
container.RegisterDecorator(typeof(ICommandHandler<>), 
    typeof(TransactionCommandHandlerDecorator<>)); 

// Decorate each returned ICommandHandler<T> object with 
// a DeadlockRetryCommandHandlerDecorator<T>. 
container.RegisterDecorator(typeof(ICommandHandler<>), 
    typeof(DeadlockRetryCommandHandlerDecorator<>)); 
+0

看起来这是一个'SimpleInjector'特定的问题。我可以告诉你像Ninject和Autofac这样的其他DI容器支持这种情况。 – neontapir

回答

3

这是你的类的声明将是什么样子?

public class CheckoutCustomerCommandHandler : 
    ICommandHandler<CheckoutCustomerCommand> {...} 

public class MoveCustomerCommandHandler : 
    ICommandHandler<MoveCustomerCommand> {...} 

这些可能看起来像他们实现相同的接口,但它们实际上编译到两个不同的接口,因为泛型参数是不同的。您的DI框架将能够区分它们。

+0

谢谢。我担心这会造成一个巨大的问题。你知道这是否适用于统一应用程序块? – user1790300

+1

Unity将不会解决您的“封闭泛型类型”的实现问题。您可能遇到的问题是如何注册装饰器,因为没有RegisterDecorator的等价物。这篇关于[Unity拦截扩展]的文章(http://www.lm-tech.it/Blog/post/2011/10/18/How-to-use-the-Unity-Interception-Extension.aspx)可能是这一步很有帮助。 – TylerOhlsen

+0

谢谢。现在检出文章。 – user1790300