2011-12-28 69 views
6

我有一個使用Autofac進行依賴注入的ASP.NET MVC Web應用程序。有時候,這個Web應用程序將啓動一個線程來執行與請求線程分開的一些工作。當此後臺線程啓動時,它會從根容器中創建一個新的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; 
} 

我的一個與Autofac註冊的依賴有兩種不同的實現:一個適用於HTTP請求的壽命和其他適合所有其他的壽命。我試過如下來註冊它們:

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

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

Autofac選擇FooForHttp HTTP請求(如預期)。然而,當我的後臺線程旋轉起來,任何試圖解決IFoo導致異常:

與標籤匹配「的HttpRequest」沒有範圍是其中要求該實例的範圍 可見。這通常表示一 部件註冊爲每個HTTP請求正在由 SingleInstance()成分reqested(或類似的情況。)在捲筒紙 積分總是請求來自 DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime, 依賴性從來沒有從容器本身。

我知道Autofac總是使用最後註冊的提供程序作爲特定組件的默認提供程序。我在這裏做了一個假設,它會使用最後註冊的合適的提供者。

我是否錯過了一些東西,還是有更好的方法來選擇基於當前生命週期範圍標記的提供者?

回答

7

正常註冊網絡Foo,但不註冊其他Foo。爲異步任務創建生命週期範圍時,請使用在ContainerBuilder上執行操作的BeginLifetimeScope()的重載。在這個動作中註冊背景Foo(b => b.Register()),並且這應該覆蓋網頁。 (小鍵盤在這裏對不起:))

+0

謝謝 - 我錯過了'BeginLifetimeScope'的重載,這正是我需要的! – 2011-12-29 03:33:13

+0

僅供參考:「Autofac.Integration.Web.ContainerProvider」類似的構造函數重載接受相同的動作。我決定從那裏提供覆蓋,因爲覆蓋是特定於Web請求的。 – 2011-12-29 03:54:54

+0

太棒了!很高興它解決了。 – 2011-12-30 04:22:50

0

這也可以通過使用標記的生命期範圍來解決。 註冊您的最前一頁富爲您所標記的範圍的實例:

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