通过简单的注入器为消费者注册装饰器

时间:2016-05-30 16:05:01

标签: c# .net dependency-injection simple-injector

假设我有两个依赖于一个界面的服务:

class Service1
{
    ...
    Service1(IDependency dependency) { ... }
    ...
}

class Service2
{
    ...
    Service2(IDependency dependency) { ... }
    ...
}

IDependency由一些具体实现注册。如何将装饰器注册到只能由Service2使用的IDependency实现?换句话说,IDependency应该仅在Service2内解析为装饰器的实例。可能吗?

1 个答案:

答案 0 :(得分:2)

您可以使用context-based injection

 // Register decorators first
 container.RegisterConditional<IDependency, DependencyDecorator1>(
     c => c.Consumer.ImplementationType == typeof(Service1));
 container.RegisterConditional<IDependency, DependencyDecorator2>(
     c => c.Consumer.ImplementationType == typeof(Service2));

 // Register the real implementation last using !c.Handled
 container.RegisterConditional<IDependency, RealImplementationDependency>(
     c => !c.Handled);

请参阅文档中的说明:

  

注意:在许多情况下,基于上下文的注入不是最佳解决方案,   并应重新评估设计。但在某些狭隘的情况下呢   可以有意义。

或者,您可以派生扩展IDependency的单独接口并使用它们,每个服务一个。这可能更适合区分依赖关系。在这种情况下,您只需为每个接口注册不同的实现/实例。

例如,您可能对云存储服务进行文件存储抽象。基本界面封装了所有文件存储操作,然后将其扩展到存储容器中的特定存储桶。您可以提供单个实现(通过委托注册),将存储桶作为每个命名接口的构造函数参数。使用标识存储桶目的的命名接口可以增强代码理解。

 public interface IFileStorage
 {
      ...
 }

 public interface IUploadStorage : IFileStorage { /* empty interface */ }

 public interface IContentStorage : IFileStorage { /* empty interface */ }

 public class FileStorage : IUploadStorage, IContentStorage
 {
      public FileStorage(string containerName)  { ... }
      ...
 }

 public UploadService(IUploadStorage storage) 
 {
     ...
 }

 public ContentService(IContentStorage storage)
 {
     ...
 }


 container.Register<IUploadStorage>(() = new FileStorage(Containers.Upload));
 container.Register<IContentStorage>(() = new FileStorage(Containers.Content));