问题(摘要)
给定一个注册依赖关系X的模块.依赖关系X在MVC3应用程序(每个HttpRequest的生存期)中具有不同的生命周期,然后在控制台应用程序中(具有名称的每个生命周期的依赖关系).在何处或如何指定依赖关系X的生命周期?
案件
我将所有与数据库相关的代码放在一个程序集中,其中包含一个注册所有存储库的模块.现在,ISession(Nhibernate)注册也在模块中.
ISession是依赖关系X(在给定的问题情况下).ISession在MVC3应用程序(每个请求的生命周期)中具有不同的生命周期,然后在控制台应用程序中定义命名的生命周期镜像.
ISession的注册是否应该在模块之外?会很奇怪,因为它是一个实现细节.
在这里做的最好的案例是什么?设计缺陷还是有智能结构:)
鉴于您的用例描述,我会说您有一些选择.
首先,您可以让每个应用程序注册自己的一组依赖项,包括生命周期范围.考虑到应用程序与注册看起来相当小的事实之间的差异,在这方面拥有一个或两个"重复"的代码片段并不是什么大不了的事.
其次,您可以将公共部分(减去生命周期范围)包装到可以在每个应用程序中使用的ContainerBuilder扩展方法中.它仍然意味着每个应用程序都有一些"重复代码",但常见的逻辑将包含在一个简单的扩展中.
public static IRegistrationBuilder<TLimit, ScanningActivatorData, DynamicRegistrationStyle>
RegisterConnection<TLimit, ScanningActivatorData, DynamicRegistrationStyle>(this ContainerBuilder builder)
{
// Put the common logic here:
builder.Register(...).AsImplementedInterfaces();
}
Run Code Online (Sandbox Code Playgroud)
在每个应用程序中使用这样的扩展名看起来像:
builder.RegisterConnection().InstancePerHttpRequest();
// or
builder.RegisterConnection().InstancePerLifetimeScope();
Run Code Online (Sandbox Code Playgroud)
最后,如果你知道它是web或非web,你可以创建一个处理交换机的自定义模块:
public class ConnectionModule : Autofac.Module
{
bool _isWeb;
public ConnectionModule(bool isWeb)
{
this._isWeb = isWeb;
}
protected override void Load(ContainerBuilder builder)
{
var reg = builder.Register(...).AsImplementedInterfaces();
if(this._isWeb)
{
reg.InstancePerHttpRequest();
}
else
{
reg.InstancePerLifetimeScope();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在每个应用程序中,您都可以注册该模块:
// Web application:
builder.RegisterModule(new ConnectionModule(true));
// Non-web application:
builder.RegisterModule(new ConnectionModule(false));
Run Code Online (Sandbox Code Playgroud)
或者,您提到您的其他应用程序中的生命周期范围具有名称.你可以让你的模块取名字:
public class ConnectionModule : Autofac.Module
{
object _scopeTag;
public ConnectionModule(object scopeTag)
{
this._scopeTag = scopeTag;
}
protected override void Load(ContainerBuilder builder)
{
var reg = builder.Register(...)
.AsImplementedInterfaces()
.InstancePerMatchingLifetimeScope(this._scopeTag);
}
}
Run Code Online (Sandbox Code Playgroud)
消费类似:
// Web application (using the standard tag normally provided):
builder.RegisterModule(new ConnectionModule("httpRequest"));
// Non-web application (using your custom scope name):
builder.RegisterModule(new ConnectionModule("yourOtherScopeName"));
Run Code Online (Sandbox Code Playgroud)
我建议不要简单地InstancePerLifetimeScope在Web应用程序中使用,除非这实际上是你想要的.如其他答案/评论中所述,InstancePerHttpRequest使用特定的命名生命周期范围,以便创建子生命周期范围是安全的; 使用InstancePerLifetimeScope没有这样的限制,所以你实际上每个子范围获得一个连接而不是请求的一个连接.我个人不认为其他开发人员不会使用子生命周期范围(这是推荐的做法),因此在我的应用程序中我非常具体.如果您完全控制您的应用程序,并且可以确保您没有创建其他子范围,或者您确实希望每个范围建立一个连接,那么可能InstancePerLifetimeScope会解决您的问题.
| 归档时间: |
|
| 查看次数: |
2200 次 |
| 最近记录: |