在 Global.asax 方法中获取在 Autofac 中注册为 InstancePerLifetimeScope 的组件的相同实例,就像注入控制器一样? [英] Get same instance of a component registered with Autofac as InstancePerLifetimeScope in Global.asax methods as is injected into a controllers?

查看:23
本文介绍了在 Global.asax 方法中获取在 Autofac 中注册为 InstancePerLifetimeScope 的组件的相同实例,就像注入控制器一样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种情况,我需要手动实例化 Application_BeginRequest 中的某些对象,这些对象依赖于我在 Autofac 注册的某些相同组件.我想使用与 Autofac 注册的组件实例相同的 InstancePerLifetimeScope 来注入我的 MVC 和 WebAPI 控制器.我的 MVC 和 Web API 配置都按预期工作,组件注册的示例如下所示:

I have a situation where I need to manually instantiate some objects in Application_BeginRequest that are dependent on some of the same components that I've registered with Autofac. I'd like to use the same instances of components that I've registered with Autofac with InstancePerLifetimeScope for injection into my MVC and WebAPI controllers. My config for both MVC and Web API works as expected, and an example of a component registration looks like so:

builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();

现在我想在我在 Application_BeginRequest 中实例化的类中使用相同的实例.我尝试了以下方法:

Now I want to use that same instance in the class I'm instantiating in Application_BeginRequest. I've tried the following methods:

//Tried with MVC controllers
DependencyResolver.Current.GetService<MyDbContext>()));
AutofacDependencyResolver.Current.ApplicationContainer.Resolve<MyDbContext>()));
AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<MyDbContext>()));
//Tried with Web API controllers
GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(MyDbContext))

但是没有人给我我正在寻找的东西,即使是在请求生命周期的后期(即超出 BeginRequest 之后).顺便说一句,我需要它来处理 Web API 配置,但我尝试了前 3 种方法只是为了看看我是否可以获得任何已解析的实例以匹配 Autofac 正在注入的内容.

But none give me what I'm looking for, even at later points in the request lifecylce (ie, beyond BeginRequest). As an aside, I need this to work with the Web API configuration, but I tried the first 3 methods just to see if I could get any of the resolved instances to match up with what Autofac is injecting.

我相信对 Autofac 中的生命周期范围有很好的理解,我的假设是我的应用程序控制器正在解析的实例位于上述 4 种方法都没有指向的子范围内,但是对我来说,上面的每种方法都试图在他们查看的范围以及他们如何决定方面做些什么是模糊的.更模糊的是 Autofac 为最终注入我的控制器的组件以及它们在创建时自动创建的生命周期范围.

I have what I believe is a decent understanding of lifetime scopes in Autofac and my assumption is that the instances that are being resolved for my application's controllers are in a child scope that the none of the above 4 methods are pointed towards, but it's fuzzy to me what each of the above methods is trying to do in regard to which scope they are looking at and how they decide. What's even fuzzier is what lifetime scopes Autofac is automatically creating for the components that are ultimately injected into my controllers and when they're created.

澄清上述几点将是一个很大的好处,但我在这里的主要问题是如何让 Autofac 将 Global.asax 中已注册组件的相同实例提供给我,它可以为 Web API 和 MVC 控制器解析?

Clarification on the points above would be a big bonus, but my primary question here is how do I get Autofac to hand me the same instances of registered components in Global.asax that it resolves for Web API and MVC controllers?

推荐答案

如果你阅读了这个主题,你会注意到人们提到在大多数情况下对于 web 应用程序, InstancePerLifetimeScopeInstancePerRequest 可以互换使用.他们没有提到的是这两个注册行为不同的例外.Gerrod 有一个 优秀文章关于 ASP.NET MVC/Web API 应用程序内部的生命周期范围以及它们如何他详细阐述了大部分省略的信息.了解这种差异对于这种情况至关重要,他的文章消除了我对 InstancePerLifetimeScope 注册与 ASP.NET 应用程序相关的任何误解.这也让我意识到,因为我需要在我的 MVC/Web API 控制器中共享解析组件的实例,InstancePerLifetimeScope 不再是合适的此应用程序的注册方式 - 我现在需要使用 InstancePerRequest.

If you read up on this subject, you'll notice that folks mention that in most circumstances for a web application, InstancePerLifetimeScope and InstancePerRequest can be used interchangeably. What they don't mention are the exceptions where these two registrations behave differently. Gerrod has an excellent article on lifetime scopes inside of ASP.NET MVC/Web API applications and how they work in which he elaborates on this piece of info that most omit. Understanding this difference is crucial to this scenario, and his article cleared up any misunderstandings I had in regards to InstancePerLifetimeScope registration in relation to ASP.NET applications. It also made me realize that, because I need to share instances of resolved components across my MVC/Web API controllers and within the global.asax, InstancePerLifetimeScope is no longer a suitable means of registration for this application- I now need to use InstancePerRequest.

根据文档, InstancePerRequest 实际上在幕后使用了 InstancePerMatchingLifetimeScope.我需要的是对位于根作用域下的标记为AutofacWebRequest"的子作用域的引用.这是我的 MVC Web API 控制器解析它们的依赖关系的范围,因为它们都使用相同的标记.那么我如何获得对该特定范围的引用?这是我的解决方案,我很想知道是否有更好的方法.

As per the docs, InstancePerRequest actually uses InstancePerMatchingLifetimeScope under the hood. What I need is a reference to the child scope that is tagged with "AutofacWebRequest" that lives under the root scope. This is the scope that both my MVC and Web API controllers resolve their dependencies from, since they both use the same tag. So how do I get a reference to that particular scope? This was my solution, and I'd love to know if there's a better way to do it.

首先,我需要从

builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();

builder.Register(c => new MyDbContext()).AsSelf().InstancePerRequest();

现在,在我构建了我的容器之后,我有以下方法:

Now, after I've built my container I have the following method:

private void SetDependencyResolversForMvcAndWebApi(ILifetimeScope container)
{
    container.ChildLifetimeScopeBeginning += CaptureRequestLifetimeScope;
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}

之前没有的唯一部分是事件订阅.每次我的容器创建一个子作用域时,我的事件处理程序都会被调用.事件处理程序如下所示:

The only part that wasn't there before is the event subscription. Everytime my container creates a child scope, my event handler gets called. The event handler looks like this:

private void CaptureRequestLifetimeScope(object sender, LifetimeScopeBeginningEventArgs args)
{
    if (args.LifetimeScope.Tag == MatchingScopeLifetimeTags.RequestLifetimeScopeTag)
    {
        //Get the ILifetimeScope created for components registered with InstancePerRequest
        var requestScope = args.LifetimeScope;

        //This is the same DbContext instance that will be injected into
        //my WebAPI and MVC controllers
        var context = requestScope.Resolve<MyDbContext>();
        //do the rest of my stuff
    }
}

我已经通过保留在 CaptureRequestLifetimeScope 事件处理程序中解析的已解析 DbContext 的引用并将其与注入到我的 Web API 和 MVC 控制器中的 DbContext 实例进行比较来对此进行测试,并且它们确实指向相同对象.

I've tested this by holding onto a reference of the resolved DbContext that's resolved within the CaptureRequestLifetimeScope event handler and comparing it to the DbContext instances that are injected into my Web API and MVC controllers, and they are indeed pointing to the same object.

这篇关于在 Global.asax 方法中获取在 Autofac 中注册为 InstancePerLifetimeScope 的组件的相同实例,就像注入控制器一样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆