使用Command / Decorator Pattern和Simple Injector从应用程序重新打印

时间:2015-03-09 15:33:11

标签: c# decorator simple-injector

所以我在处理某些命令后使用装饰器进行打印。我的问题是用户是否想要发行转载。我创建了一个从UI层发送的Reprint命令类,但Reprint命令不需要PrintDecorator的单独处理程序,因为重新打印处理正是打印装饰器中的所有内容。是否有策略仅使用PrintDecorator定位SimpleInjector?我知道这可能违背了模式,但我能想到的唯一方法是为reprint命令创建一个空的命令处理程序,但这似乎不对。感谢。

  public class Reprint : ICommandParam, IPrintFrom
  {
    public string Id { get; set; }
    public string Printer { get; set; }
    public int Copies { get; set; }
  }

  public class PrintDecorator<TCommand> : ICommandHandler<TCommand>
    where TCommand : IPrintFrom
  {
    private readonly IFooService _svc;
    private readonly ICommandHandler<TCommand> _handler;

    public PrintDecorator(IFooService svc, ICommandHandler<TCommand> handler)
    {
      if (svc == null)
        throw new ArgumentNullException("IFooService");

      _svc = svc;
      _handler = handler;
    }

    [Import] // optional
    public IDatabase Database { get; set; }

    public void Handle(TCommand commandParm)
    {
      if (_handler != null)
        _handler.Handle(commandParm);

      svc.GetDataFromService(commandParm.id);
      svc.PrintData(commandParm.Printer, commandParm.Copies);    
      if (Database != null && commandParm.Copies > 0) {
        // TODO - add a print record
      }
    }
  }

1 个答案:

答案 0 :(得分:2)

这完全取决于你想要什么。我的建议是将重新打印逻辑保持在一个真实的ReprintCommandHandler内(可能通过注入一个与装饰器相同的方式进行打印的服务)。这对我来说似乎是合理的,因为在重印的情况下,重印是实际的商业逻辑,而不是交叉问题。

在这种情况下,您必须排除在PrintDecorator周围装饰ReprintCommandHandler,这可以按照以下方式完成:

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(PrintDecorator<>),
    c => c.ServiceType != typeof(ICommandHandler<Reprint>));

另一方面,如果您希望将打印逻辑保留在PrintDecorator内,而不必在业务层中复制此逻辑,则可以实现完全空ReprintCommandHandler,或者您可以注册一个特殊的Null Object命令处理程序。

使用空处理程序当然是简单的,这将使您的配置非常简单:

// NOTE: Use RegisterManyForOpenGeneric for Simple Injector v2.x
container.Register(typeof(ICommandHandler<>),
   new[] { typeof(ICommandHandler<>).Assembly });

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(PrintDecorator<>));

下行当然是你需要一个空类。所以另一种方法是实现Null Object模式,如下所示:

public class NullCommandHandler<T> : ICommandHandler<T> {
    public void Handle(T command) { }
}

如果您有多个空实现,可以重复使用此实现,您可以按如下方式注册:

// NOTE: Use RegisterManyForOpenGeneric for Simple Injector v2.x
container.Register(typeof(ICommandHandler<>),
   new[] { typeof(ICommandHandler<>).Assembly });

container.Register<ICommandHandler<Reprint>, NullCommandHandler<Reprint>>();

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(PrintDecorator<>));