我有下面的继承,我想用简单的注入器来装饰(重命名的东西,以使它更易读):
interface IGetData<T,U> { }
interface ICustomerService : IGetData<Customer, Guid> { }
class CustomerServiceImpl : ICustomerService { }我为IGetData<T,U>有一个名为GetDataDecorator的装饰师,为ICustomerService有另一个名为CustomerServicePermissionDecorator的装饰师。我的目标是为CustomerServiceImpl设置两个(链式)装饰器,一个是基于IGetData<T,U>接口的,一个是基于ICustomerService接口的。我在初创公司注册了这两家装修公司:
container.RegisterDecorator<ICustomerService, CustomerServicePermissionDecorator>();
container.RegisterDecorator(typeof(IGetData<,>), typeof(GetDataDecorator<,>));第一次注册工作正常,CustomerServiceImpl中的一个断点显示那里的方法是从CustomerServicePermissionDecorator调用的。然而,GetDataDecorator方法从未被执行过。
我想这是我的误解-我做错什么了?
发布于 2018-11-29 11:53:18
在这些复杂的情况下,手工编写对象图通常会有所帮助,因为这样可以更直观地看到正在发生的事情。它甚至允许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正如您在第三行中所看到的,从技术上讲,可以用一个ICustomerService装饰器来装饰一个GetDataDecorator<Customer, Guid>。但是,由于GetDataDecorator<T, U>没有实现ICustomerService,所以不可能将该装饰器插入到任何期望使用ICustomerService的消费者中。这就是为什么示例中的最后一行代码会出现编译错误的原因。
由于这个对象图不能用普通的旧C#来构造,所以简单的注入器也不能这样做。它受公共语言运行时()的限制。
但是,在本例中,Simple Injector比CLR限制性更强,因为前面示例中的任何ICustomerService都可以使用GetDataDecorator<Customer, Guid>来修饰。可以构造依赖于GetData<Customer, Guid>的消费者。但是简单的喷射器不允许这样做。
不允许这样做的原因之一是为了防止非常复杂和混乱的情况,在某些情况下使用装饰器,而在其他情况下忽略。这就是为什么简单的注入器强迫您显式地声明应用装饰器的接口。简单注入器将而不是在继承链中寻找基本接口,这似乎是您所期望的行为。
虽然很难对您的设计进行评论,但是您可能需要考虑一起删除ICustomerService。特别是因为您已经在使用泛型接口。我经常看到开发人员试图通过在泛型和非泛型之间混合使用他们的旧接口(这很可能是ICustomerService ),但这很难奏效。您应该完全进入并放弃过于广泛的、非一般的接口。当你这样做的时候,简单的喷射器会简化你的装饰程序。
https://stackoverflow.com/questions/53537171
复制相似问题