2011-12-28 1 views
6

종속성 주입을 위해 Autofac을 사용하는 ASP.NET MVC 웹 응용 프로그램이 있습니다. 때때로이 웹 응용 프로그램은 요청 스레드와 별도의 작업을 수행하기 위해 스레드를 시작합니다. 이 배경 스레드가 시작되면 루트 컨테이너에서 새로운 Autofac 수명 범위를 설정하고 몇 가지 작업을 실행합니다. 하나의 HTTP 요청 수명에 대한 적절하고 다른 모든 생애에 대한 또 다른 적절한 : Autofac에 등록 된 내 종속성일치하는 평생주기 범위 내의 Autofac 수명 및 기본 공급자

public IAsyncResult Run<T>(Action<T> action) 
{ 
    var NewTask = System.Threading.Tasks.Task.Factory.StartNew(() => 
    { 
     using (var Scope = Runtime.Container.BeginLifetimeScope()) 
     { 
      var Input = Scope.Resolve<T>(); 
      action(Input); 
     } 
    }); 

    return NewTask; 
} 

하나는 두 개의 서로 다른 구현을 가지고있다.

builder 
.Register(c => new Foo()) 
.As<IFoo>() 
.InstancePerLifetimeScope(); 

builder 
.Register(c => new FooForHttp(HttpContext.Current)) 
.As<IFoo>() 
.InstancePerMatchingLifetimeScope(WebLifetime.Request); 

Autofac는 HTTP 요청을 FooForHttp 선택 (예상대로) : 나는 다음과 같이 그들을 등록했습니다.

태그 일치하는 'HttpRequest에'아니오 범위는 인스턴스가 요청 된의 범위 에서 볼 수있다 : 내 백그라운드 스레드가 회전 할 때, 어떤 시도는 예외 IFoo 결과를 해결할 수 있습니다. 이것은 일반적으로 구성 요소로 등록되어 있음을 나타냅니다 당 HTTP 요청이 웹 통합에서 (. 또는 유사한 시나리오)을 SingleInstance() 구성 요소에 의해 reqested 항상 DependencyResolver.Current 또는 ILifetimeScopeProvider.RequestLifetime, 에서 종속성을 요청하고 있습니다 결코 컨테이너 자체에서.

저는 Autofac이 항상 마지막으로 등록 된 공급자를 특정 구성 요소의 기본 공급자로 사용한다는 것을 알고 있습니다. 나는 여기에 최종 등록 된 제공자를 사용할 것이라고 가정했다.

내가 누락되었거나 현재 수명 범위의 태그를 기반으로 공급자를 선택하는 더 나은 방법이 있습니까?

답변

7

웹 Foo를 정상적으로 등록하지만 다른 Foo를 등록하지 마십시오. 비동기 태스크의 수명 범위를 작성할 때 ContainerBuilder에서 조치를 취하는 BeginLifetimeScope()의 오버로드를 사용하십시오. 이 작업 (b => b.Register())에 배경 Foo를 등록하면 웹에 우선 적용됩니다. (작은 키보드는 여기에 미안합니다 :)

+0

감사합니다. 'BeginLifetimeScope'에 대한 과부하가 그리워졌습니다. –

+0

FYI : 동일한 작업을 허용하는 Autofac.Integration.Web.ContainerProvider'에 대해 유사한 생성자 오버로드가 있습니다. 오버라이드는 웹 요청과 관련이 있으므로 오버라이드를 제공하기로 결정했습니다. –

+0

좋아요! 그것이 다행했기 때문에. –

0

이것은 또한 태그 수명 시간 범위를 사용하여 해결할 수 있습니다. 당신의 태그 범위의 인스턴스로 당신의 fisrt 푸 등록 :

builder.RegisterType<Foo>().As<IFoo>.InstancePerMatchingLifetimeScope("YourScopeTag"); 

그리고 같은 태그를 사용하여 범위를 만들 당신은 당신의 dependencie 등록 :

그것을 테스트하지 않은,하지만이

작동합니다

using (var Scope = Runtime.Container.BeginLifetimeScope("YourScopeTag")) 
     { 
      var Input = Scope.Resolve<T>(); 
      action(Input); 
     } 

http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-matching-lifetime-scope