我正在使用Autofac与ASP.NET Webforms。当我在global.asx的App_Start方法中注册依赖项时,我想了解InstancePerLifetimeScope和InstancePerRequest之间的区别。
看起来对于它们两者来说,依赖关系的新实例只在Every HttpRequest中创建一次(通过断点进入依赖关系的构造函数和对象的HashCode)。
有任何想法吗?
谢谢
@Travis提供了描述其工作原理的文档的良好链接。但是,我更愿意举一些例子来更好地说明理论。那么,让我们来看一个简单的例子。
假设您有两个类ClassA和ClassB实现了一些简单的接口IClassA和IClassB。
public class ClassA : IClassA
{
public ClassA() {
}
}
public class ClassB : IClassB
{
public ClassB() {
}
}
现在,让我们看看当我们以不同的方式注册它们时会发生什么。
例A
builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IClassA>().InstancePerLifetimeScope();
builder.RegisterType<ClassB>().As<IClassB>().InstancePerLifetimeScope();
然后,在控制器中,您执行以下操作:
public class HomeController : Controller
{
private readonly IClassA _classA;
private readonly IClassB _classB;
private readonly IComponentContext _ctx;
public HomeController(IClassA classA, IClassB classB, IComponentContext ctx) {
_classA = classA;
_classB = classB;
_ctx = ctx;
}
public string Get() {
using (var scope = _ctx.BeginLifetimeScope()) {
var newClassA = scope.Resolve<IClassA>(); // Object.ReferenceEquals(newClassA, _classA) == false
var newClassB = scope.Resolve<IClassB>(); // Object.ReferenceEquals(newClassB, _classB) == false
return "Ok";
}
}
}
在此示例中,Get()方法中的两个“新”变量将接收新实例,因为它们都被注册为每个生命周期范围内唯一。我们开始了新的生命范围 - 我们得到了新的实例。
现在,我们来看看另一个例子。
例B
builder = new ContainerBuilder();
builder.RegisterType<ClassA>().As<IClassA>().InstancePerLifetimeScope();
builder.RegisterType<ClassB>().As<IClassB>().InstancePerRequest(); // now they have different life time!
// controller:
public class HomeController : Controller
{
private readonly IClassA _classA;
private readonly IClassB _classB;
private readonly IComponentContext _ctx;
public HomeController(IClassA classA, IClassB classB, IComponentContext ctx) {
_classA = classA;
_classB = classB;
_ctx = ctx;
}
public string Get() {
using (var scope = _ctx.BeginLifetimeScope()) {
var newClassA = scope.Resolve<IClassA>(); // Object.ReferenceEquals(newClassA, _classA) == false
var newClassB = scope.Resolve<IClassB>(); // Object.ReferenceEquals(newClassB, _classB) == true
return "Ok";
}
}
}
看看这里发生了什么?即使我们开始了新的生命周期范围 - 仍然可以从请求范围而不是从我们的新范围中解析ClassB。这是InstancePerLifetimeScope()和InstancePerRequest()之间的区别。
正如文档所暗示的那样,内部它基于另一个Autofac概念 - InstancePerMatchingLifetimeScope()。
在许多情况下,它相同。 This is an FAQ on the Autofac doc site.