2017-02-02 25 views
0

我被利用AutoFac的ServiceHost.AddDependencyInjectionBehavior()擴展(如Autofac documentation描述)注入業務層爲自託管(InstanceContextMode =每個呼叫)WCF服務Autofac自託管的WCF服務和對象的處置

我的業務層使用的組件每次有新的請求進入時都不能重新創建(假設它需要持久的數據庫連接)。

因此,構建容器時,我想作爲一個實例,即:註冊BL服務

builder.RegisterType<BusinessLayer>() 
    .SingleInstance(); 

業務層注入WCF服務工作正常;我的問題是:

Dispose()不會在容器中創建的任何服務上調用:不僅僅是業務層本身,也是'持久'服務。

我預計這會發生在BL服務本身。從Autofac docs再次:

如果你有單組分(註冊SingleInstance()),他們將住在集裝箱的生活。由於容器使用壽命通常是應用程序的使用壽命,這意味着組件 將不會在應用程序結束前處理。

,偏偏沒有我的「孩子」(Autofac註冊)服務(即「IPersistentService」下面)的處置時的壽命範圍 - 因爲我不是明確地讓他們「SingleInstance 「? 備註::如果我在關閉ServiceHost後手動處理業務層服務,仍然是這種情況

E.g. (略去了IDisposable的實現):

[ServiceContract] 
public interface IMyService 
{ 
    void DoStuff(); 
} 
public class MyService : IMyService 
{ 
    IBusinessLayer _bl; 
    public MyService(IBusinessLayer bl) 
    { 
     _bl = bl; 
    } 

    public void DoStuff() 
    { 
     _bl.BLDoStuff(); 
    } 
} 

public interface IBusinessLayer 
{ 
    void BLDoStuff(); 
} 
public class BusinessLayer : IBusinessLayer 
{ 
    IPersistentService _service; 
    public BusinessLayer(IPersistentService service) 
    { 
     _service = service; 
    } 
    public void BLDoStuff() 
    { 
     // Do something that requires a 'cached'/persistent component 
     _service.DoSomethingWithPersistentConnection(); 
    } 
} 

public interface IPersistentService : IDisposable 
{ 
    void DoSomethingWithPersistentConnection(); 
} 

隨着Autofac註冊看起來像:

builder.RegisterType<BusinessLayer>() 
    .SingleInstance(); 

builder.RegisterType<MyPersistentService>() 
    .As<IPersistentService>() 
    .OnActivated(e => e.Instance.Start()); 
+0

「爲什麼我的'孩子'(Autofac註冊的)服務(即下面的'IPersistentService')沒有一個在終生範圍是」時處理「。這個問題通常被稱爲[Captive Dependency](俘虜依賴)(http://blog.ploeh.dk/2014/06/02/captive-dependency/)。 – Steven

+0

沒錯。葉,這解釋了它 - 並感謝與該描述的鏈接。 – Ive

回答

1

正如史蒂芬提到的,你在這裏體驗到什麼是圈養依賴性問題。換句話說,一個單身人士(BusinessLayer,註冊.SingleInstance())保留了終身範圍或臨時依賴(MyPersistentService,默認登記爲瞬態)。

這樣說,單身服務的依賴關係本身總是單身人士,不管他們是如何在容器中註冊的。 Steven鏈接到的Mark Seeman's article圖表給出了一個很好的觀點。

我認爲你可以達到你的預期,但你的註冊是錯誤的。

我的業務層使用的組件在每次有新的請求進來時(假設它需要持久的數據庫連接)都無法重新創建。

因此,構建容器時,我想作爲一個實例

這就是問題的所在註冊BL服務。這是商業服務的依賴關係必須註冊爲單例,而不是商業服務本身。這意味着您可以讓Autofac爲每個WCF調用創建一個不同的BusinessLayer實例,但注入的MyPersistentService實例始終是相同的。這有意義嗎?然後,您的註冊會是什麼樣子:

builder 
    .RegisterType<BusinessLayer>() 
    .As<IBusinessLayer>() 
    .InstancePerLifetimeScope(); // a new instance per WCF call 

builder 
    .RegisterType<MyPersistentService>() 
    .As<IPersistentService>() 
    .OnActivated(e => e.Instance.Start()) 
    .SingleInstance(); // one same instance for the lifetime of the application 

MyPersistenService的一個實例,然後將配置的根容器(即通過調用builder.Build()創建)在關閉服務主機後後丟棄只。

+0

感謝您的解釋 - 是的,正如@Steven也提到的那樣,所謂的「俘虜依賴」正是我的問題。然而,我真的很喜歡使用Autofac的對象處理來清理「持久」服務。這聽起來不像是這樣,但如果我將它們定義爲單例 - 因此我試圖通過使BL服務變成單例來解決這個問題。 – Ive

+0

我不明白。如果無法爲每個請求重新創建持久服務,那麼爲什麼要在每次請求之後處理它呢?這聽起來與我矛盾。 –

+0

我不想在每次請求後處理它們,而是在關閉服務時處理它們。我的服務生命週期跨越了我的WCF serviceHost打開的時間。 – Ive