【问题标题】:Simple Injector: Decorator for multiple interfacesSimple Injector:多个接口的装饰器
【发布时间】:2019-05-01 09:46:20
【问题描述】:

我有以下继承,我想用 Simple Injector 装饰(重命名的东西使其更具可读性):

interface IGetData<T,U> { }
interface ICustomerService : IGetData<Customer, Guid> { }
class CustomerServiceImpl : ICustomerService { }

我有一个用于IGetData&lt;T,U&gt; 的装饰器,名为GetDataDecorator,我还有另一个用于ICustomerService 的装饰器,名为CustomerServicePermissionDecorator。我的目标是为CustomerServiceImpl 提供两个(链接的)装饰器,一个基于IGetData&lt;T,U&gt; 接口,一个基于ICustomerService 接口。我在启动时注册了两个装饰器:

container.RegisterDecorator<ICustomerService, CustomerServicePermissionDecorator>();
container.RegisterDecorator(typeof(IGetData<,>), typeof(GetDataDecorator<,>));

第一次注册工作正常,CustomerServiceImpl 中的断点表明那里的方法是从CustomerServicePermissionDecorator 调用的。但是,GetDataDecorator 方法永远不会执行。

我想这是我的一个误解 - 我做错了什么?

【问题讨论】:

  • 我对你的问题有点困惑,我可以建议你包含足够的代码来让复制粘贴重现问题吗?然后更好地解释一下“用简单的注射器装饰”是什么意思?你想让接口传递的Instance装饰在容器的实例上吗?还是什么?
  • 我想你是从容器中请求ICustomerService?您仅将容器配置为使用CustomerServicePermissionDecorator 装饰ICustomerService - 您尚未将ICustomerService 配置为由GetDataDecorator&lt;,&gt; 装饰。
  • @qujck 我认为ICustomerService 会在实现IGetData&lt;T,U&gt; 时被隐式修饰——事实并非如此,是吗?
  • @MortenBork 该实例应该使用继承接口的两个装饰器来装饰(通过 SimpleInjector)。我会尝试创建一个更详细的示例。
  • @PhilReif SimpleInjector 不会做出这样的假设

标签: c# dependency-injection decorator simple-injector


【解决方案1】:

在这些复杂的情况下,手动编写对象图通常会有所帮助,因为这样可以更直观地看到正在发生的事情。它甚至允许 C# 编译器发出无法解决的问题。

根据您指定的设计,您可以手动构建以下对象图。

ICustomerService impl = new CustomerServiceImpl();

ICustomerService dec1 = new CustomerServicePermissionDecorator(impl);

IGetData<Customer, Guid> dec2 = new GetDataDecorator<Customer, Guid>(dec1);

// Consumer depends on ICustomerService 
var consumer = new Consumer(dec2); <-- compile error

正如您在第三行中看到的那样,从技术上讲,可以使用 GetDataDecorator&lt;Customer, Guid&gt; 装饰器来装饰 ICustomerService。然而,因为GetDataDecorator&lt;T, U&gt; 没有实现ICustomerService,所以不可能将该装饰器注入任何期望ICustomerService 的消费者。这就是示例中最后一行代码给出编译错误的原因。

而且由于这个对象图不能使用普通的旧 C# 构建,Simple Injector 也无法做到这一点。它受到公共语言运行时的限制。

然而,在这种情况下,Simple Injector 比 CLR 更具限制性,因为前面示例中的任何 ICustomerService 都可以用 GetDataDecorator&lt;Customer, Guid&gt; 进行修饰。可以构造一个依赖于GetData&lt;Customer, Guid&gt; 的消费者。但是 Simple Injector 不允许这样做。

不允许这样做的原因之一是为了防止出现非常复杂和令人困惑的情况,其中装饰器在某些情况下被应用,但在其他情况下被省略。这就是为什么 Simple Injector 强制你明确声明应该应用装饰器的接口。 Simple Injector 不会遍历继承链来寻找基本接口,这似乎是您所期望的行为。

虽然很难评论您的设计,但您可能需要考虑将ICustomerService 一起删除。特别是因为您已经在使用通用接口。我经常看到开发人员试图通过在泛型和非泛型之间进行混合来保留他们的旧接口(@98​​7654331@ 很可能是这样),但这很难奏效。您应该全力以赴并放弃过于宽泛的非通用接口。当您这样做时,Simple Injector 将为您简化应用装饰器。

【讨论】:

  • 感谢您的详尽解释。消除 ICustomerService 可能会带来其他问题,但我会按照您的想法从这里开始调查
猜你喜欢
  • 1970-01-01
  • 2016-06-07
  • 2014-03-21
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多