Autofac - InstancePerLifetimeScope与ASP.NET Web窗体中Application_Start中的InstancePerRequest

时间:2018-04-02 14:04:47

标签: autofac

我正在使用Autofac和ASP.NET Webforms。当我在global.asx的App_Start方法中注册依赖项时,我想了解InstancePerLifetimeScope和InstancePerRequest之间的区别。

对于他们两个来说,在Every HttpRequest中只创建一次新的依赖实例(使用断点进入依赖关系的构造函数和对象的HashCode)。

有什么想法吗?

谢谢

2 个答案:

答案 0 :(得分:2)

在许多情况下,它相同。 This is an FAQ on the Autofac doc site.

答案 1 :(得分:1)

@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()