根据您的用例描述,我认为您有几个选择。
首先,您可以让每个应用程序注册自己的依赖项,包括生命周期范围。在这方面有一两个“重复”的代码并不是什么大问题,考虑到应用程序之间的差异以及注册似乎相当小。
其次,您可以将公共部分(减去生命周期范围)包装成一个ContainerBuilder扩展方法,该方法可在每个应用程序中使用。这仍然意味着每个应用程序都有一些“重复代码”,但是公共逻辑将被包装在一个简单的扩展中。
public static IRegistrationBuilder<TLimit, ScanningActivatorData, DynamicRegistrationStyle>
RegisterConnection<TLimit, ScanningActivatorData, DynamicRegistrationStyle>(this ContainerBuilder builder)
{
builder.Register(...).AsImplementedInterfaces();
}
使用这样的扩展,在每个应用程序中的使用方式如下所示:
在每个应用程序中使用此扩展的代码如下:
builder.RegisterConnection().InstancePerHttpRequest();
builder.RegisterConnection().InstancePerLifetimeScope();
最后,如果你知道这是网站还是非网站,你可以创建一个自定义模块来处理开关:
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();
}
}
}
在每个应用程序中,您都可以注册该模块:
// Web application:
builder.RegisterModule(new ConnectionModule(true));
// Non-web application:
builder.RegisterModule(new ConnectionModule(false));
另外,你提到你其他应用程序中的lifetime scope有一个名称。 你可以让你的模块采用这个名称:
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);
}
}
消费类似:
// 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"));
我建议在Web应用程序中不要简单地使用InstancePerLifetimeScope
,除非这确实是你想要的。正如其他答案/评论中指出的那样,
InstancePerHttpRequest
使用特定的命名生命周期范围,以便安全地创建子生命周期范围;而使用
InstancePerLifetimeScope
没有这样的限制,因此会为每个子范围实际上获取一个连接,而不是每个请求获取一个连接。就我个人而言,我不认为其他开发人员不会使用子生命周期范围(
这是推荐的做法),因此在我的应用程序中我非常具体。如果您完全控制应用程序,并且可以保证您不会创建额外的子范围,或者您确实希望每个范围都有一个连接,那么也许
InstancePerLifetimeScope
可以解决您的问题。