有RegisterPerWebRequest
和RegisterWithContext
(这个版本最初不附带简单的注入器,但是它在advanced-scenarios section上提供)。另外两种方法都可以正常工作,但我需要将它们结合起来。
我发现RegisterPerWebRequest
使用了new WebRequestLifestyle()
生活方式(找到它there)。因此,我提供Lifestyle.Transient
而不是RegisterWithContext
new WebRequestLifestyle()
,但DependencyContext.ImplementationType
和DependencyContext.ServiceType
似乎为空。
这有什么问题?
更新1。
所以我想像RegisterPerWebRequest
一样注册每个Web请求的类型,但也能够为实例创建者提供访问注册类型的类型的访问权。
我修改了(将生活方式作为参数提取)RegisterWithContext
为:
public static void RegisterWithContext<TService>(
this Container container,
Func<DependencyContext, TService> contextBasedFactory, Lifestyle lifestyle)
where TService : class
{
//original code
container.Register<TService>(rootFactory, lifestyle);
//original code
}
对于“每个网络请求和上下文”注册,我希望能够使用:
container.RegisterWithContext<IUnitOfWork>(dependencyContext =>
{
var implementationType = dependencyContext.ImplementationType;
//do some stuff and return preconfigured UnitOfWork
}, new WebRequestLifestyle());
正如我已经提到的,dependencyContext.ImplementationType
是NULL
我正在使用SimpleInjector 2.3.0.0
答案 0 :(得分:8)
RegisterWithContext
扩展方法显式将提供的委托注册为Transient
。这样做是因为将类型注册到任何其他生活方式都没有意义。
WebRequestLifestyle
这样的生活方式的想法是在整个对象图中缓存和重用相同的实例(可能超出该范围)。然而,这个概念在处理基于上下文的注册时没有多大意义,因为基于上下文的实例每次注入时都会有所不同。换句话说,为每个消费者提供一个唯一的实例与重用相同实例的概念相冲突。
例如,查看以下对象图:
new HomeController(
new Logger("HomeController"),
new LoggingRepositoryDecorator<User>(
new Logger("LoggingRepositoryDecorator<User>"),
new SqlRepository<User>(
new DbContext())),
new LoggingCommandHandlerDecorator<ShipOrder>(
new Logger("LoggingCommandHandlerDecorator<ShipOrder>"),
new ShipOrderCommandHandler(
new DbContext())));
在这个对象图中,我们创建了一个带有依赖关系的HomeController
。 Logger
组件显然是基于上下文的组件,因为它每次都基于其父级进行不同的初始化。这将是Logger
的注册:
container.RegisterWithContext<ILogger>(context =>
new Logger(context.ImplementationType.Name));
但是如果我们允许ILogger
注册注册WebRequestLifestyle
,则每次都应该应用相同的实例,这可能会导致以下对象图:
ILogger logger = new Logger(typeName: "HomeController");
new HomeController(
logger,
new LoggingRepositoryDecorator<User>(
logger,
new SqlRepository<User>(
new DbContext())),
new LoggingCommandHandlerDecorator<ShipOrder>(
logger,
new ShipOrderCommandHandler(
new DbContext())));
在此对象图中注入了相同的Logger("HomeController")
,这显然不是我们想要的。此外,行为变得非常不可预测,因为首先创建的是消费者,这将决定在整个图中重用的记录器typeName
。但是没有人会期望从ILogger
的构造函数中删除HomeController
会导致LoggingCommandHandlerDecorator<ShipOrder>
的记录器发生变化。
这就是Lifestyle
扩展方法中没有RegisterWithContext
参数的原因。