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