作为注入到控制器获取关于Autofac如InstancePerLifetimeScope Global.asax中的方法注册的部件的相同的实例? [英] Get same instance of a component registered with Autofac as InstancePerLifetimeScope in Global.asax methods as is injected into a controllers?

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

问题描述

我有一个情况我需要手动实例化的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))

但没有给我什么我要找的,即使在请求lifecylce点以后(即超越的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递给我,它解决的Web API和MVC控制器在Global.asax中注册的组件相同的实例?

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应用程序, InstancePerLifetimeScope InstancePerRequest 可以互换使用。他们不提在哪里这两个登记行为不同的异常。 Gerrod 拥有的优秀文章终生范围的ASP.NET MVC /网络API的应用程序以及它们如何工作在里面,他详细阐述了这片信息的,大多数省略。理解这种差异是此方案的关键,他的文章澄清了误解我曾在关于 InstancePerLifetimeScope 注册有关ASP.NET应用程序。这也使我认识到,因为我需要分享在我的MVC /网页API控制器解决组件的实例的在Global.asax中, 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的的网页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.

首先,我需要我的注册从

First off, I need to change my registration from

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
    }
}

我已经通过持有到解决的一个参考的DbContext这就是CaptureRequestLifetimeScope事件处理程序中解决,比较它被注入到我的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.

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

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