【问题标题】:command pattern using Dependency Injection for MVC 3 controller使用 MVC 3 控制器的依赖注入的命令模式
【发布时间】:2012-10-22 10:12:38
【问题描述】:

我阅读了以下文章.NET Junkie - Meanwhile... on the command side of my architecture,该文章由另一位 stackoverflow 用户提出,该文章概述了命令模式,并在文章末尾提供了如何将其与 DI 一起使用的策略。

这有很大帮助,但我缺少一件事,假设我创建了一个名为 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<>));

【问题讨论】:

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

标签: c# asp.net-mvc-3 dependency-injection command-pattern simple-injector


【解决方案1】:

这是您的类声明的样子...

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

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

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

【讨论】:

  • 谢谢。我担心这会带来一个巨大的问题。你知道这是否适用于统一应用程序块?
  • Unity 在解决“封闭泛型类型”的实现时不会遇到任何问题。您可能会遇到的问题是如何注册装饰器,因为没有与 RegisterDecorator 等价的东西。 Unity Interception Extension 上的这篇文章可能会对这一步有所帮助。
  • 谢谢。立即查看文章。
  • 为了记录,我使用了 SimpleInjector 装饰器,它们工作得很好。
猜你喜欢
  • 2011-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多