在此代码中:
container.Register<IDataHoldingSession<DbContext>, EntityFrameworkSession>();
container.RegisterAll<ISession>(typeof(IDataHoldingSession<DbContext>));
container.RegisterDecorator(typeof(IDataHoldingSession<>), typeof(ValidatingSession<>));
当要求容器IEnumerable<ISession>
时,会给它一个包含EntityFrameworkSession
的集合,但不会应用装饰器。如何在上面的代码中应用装饰器?
我认为这是因为没有要求容器IEnumerable<IDataHoldingSession<T>>
。我将RegisterAll
的XML文档解释为暗示在这种情况下将要求容器提供IDataHoldingSession<DbContext>
的实例,我认为这应该会导致应用装饰器。但是,由于使用RegisterAll
服务类型调用ISession
,因此可能会绕过装饰器。
答案 0 :(得分:3)
我能够通过向Registration
提供RegisterAll
来解决此问题。我将每个注册的服务类型设置为其特定的服务类型,而不是ISession
。
这是一个演示此内容的扩展方法:
/// <summary>
/// Same as <see cref="Container.RegisterAll"/>, except each implementation service
/// is individually resolved from the container for compatibility with decorators.
/// </summary>
public static void RegisterAllBugFixed<TService>(this Container container,
params Type[] serviceTypes)
{
var registrations =
from serviceType in serviceTypes
select Lifestyle.Transient.CreateRegistration(
serviceType,
() => container.GetInstance(serviceType),
container);
container.RegisterAll(typeof(TService), registrations);
}
答案 1 :(得分:2)
Simple Injector中的注册包含两部分:
InstanceProducer
。这是对象生成实例并负责拦截和装饰实例。 InstanceProducer
不知道注册的TImplementation
,只知道TService
。InstanceProducer
包裹Registration
个对象。该对象负责构建一个创建实例的Expression,构造函数注入,属性注入,自定义初始化,并将生活方式应用于表达式。 Registration
(仅)知道TImplementation
。当您进行RegisterAll
注册时,您提供的类型会引用容器中的其他注册。您是通过Register<IDataHoldingSession<DbContext>>
同时在RegisterAll
注册中使用该接口类型来实现此目的。
RegisterAll
所涵盖的内容是查询容器以获取给定类型的注册(在您的情况下为IDataHoldingSession<DbContext>
)。由于请求的类型可能与集合的服务类型不同(通常是这样,并且在您的情况下),容器从找到的Registration
中抓取InstanceProducer
并创建新的{{1}基于该InstanceProducer
的集合的实际服务类型。这在Simple Injector源代码(Registration
)中如下所示:
ContainerControlledCollection
但是由于装饰器由return new InstanceProducer(typeof(TService), instanceProducer.Registration);
应用,我们会丢失您应用于InstanceProducer
的装饰器。
坦率地说,我不确定为什么我们实现了这样的行为,因为最直观的行为会让IDataHoldingSession<T>
的装饰器仍然被应用。我想我们试图阻止装饰器被施加两次;这是Simple Injector早期版本中的一个问题。
我会试着调查一下,看看我是否可以为v2.4找到一个修复程序,但是如果我不引入一个重大变化,我只能这样做。与此同时,我认为您发现自己的解决方法非常好。如果我做了修复,我可能会在内部实现它,就像你现在做的那样。
我很遗憾Simple Injector没有按照你预期的方式工作。
<强>更新强>
我刚刚检查了修复this issue的主分支中的错误修复程序。 v2.4 release包含此修复程序。