2016-09-26 52 views
1

我試圖解決ASP.Net WebApi 2項目的StartUp類中的依賴關係。 Autofac用於配置依賴注入。場景如下:在StartUp中使用Autofac解決每個用戶/每個請求的依賴關係

  • 不同的用戶看到不同的數據。每個用戶都有一定的權限,允許用戶查看某些數據。
  • 正在使用包含多個邊界的域驅動架構。不允許在域和數據訪問層進行跨界調用。這很重要,因爲爲了獲得用戶允許的數據的所有代碼,我們需要做一些跨境呼叫。
  • 我們想過濾數據訪問層內的數據,只爲每個用戶檢索允許的數據。這裏不允許跨境呼叫。
  • 爲了達到這個目標,我想從用戶可以看到的記錄中注入所有代碼的列表。
  • 爲此,我嘗試使用Autofac註冊一個工廠,該工廠基於用戶創建此列表。我們打電話給工廠StuffFactory和名單StuffModel

現在的問題是,所有這些都需要註冊爲InstancePerRequest。這會引發InvalidOperatonException,這聽起來很合理,因爲請求生命週期範圍無法在StartUp中訪問?

從請求實例的作用域中看不到具有標籤匹配'AutofacWebRequest'的作用域。這通常表示按照Single-HTTP請求註冊的組件正在通過SingleInstance()組件(或類似的場景)請求。在Web集成下,始終請求DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime的依賴關係,而不是從容器本身。

在允許的東西是在容器的註冊代碼:

private IContainer RegisterAllowedStuff(IContainer container) 
{ 
    var builder = new ContainerBuilder(); 

    builder.Register(x => GetAllowedStuffForUser(container)) 
     .As<StuffModel>() 
     .InstancePerRequest(); 

    builder.Update(container); 
    return container; 
} 

private static StuffModel GetAllowedStuffForUser(IContainer container) 
{ 
    var stuffFactory = container.Resolve<IStuffFactory>(); 
    return stuffFactory.CreateStuffModel(Helper.GetParsedUserName()); 
} 

我有點停留在如何從這裏前進。對於我完全監督的Autofac問題,是否有一個簡單的解決方案?有人可能對我如何實現這一點有更好的想法嗎?提前致謝!

回答

4

您的啓動班不應該有任何業務邏輯。 Autofac允許您註冊將在解析時調用的lambda方法。目前,HttpRequest可用,因此您可以將這些lambda註冊爲InstancePerRequest

在你的情況,如果你想註冊一個StuffModelInstancePerRequest你可以做這樣的:

builder.RegisterType<ConcreteStuffFactory>() 
     .As<IStuffFactory>(); 
builder.Register(c => c.Resolve<IStuffFactory>() 
         .CreateStuffModel(Helper.GetParsedUserName())) 
     .As<IStuffModel>() 
     .InstancePerRequest(); 

順便說一句,我也不會用的輔助類,它看起來像一個反模式,您可以創建一個服務來獲取當前用戶的用戶名,例如IUserContextProvider。您還可以添加在ConcreteStuffFactory

public class ConcreteStuffFactory 
{ 
    public ConcreteStuffFactory(IUserContextProvider userContextProvider) 
    { 
     this._userContextProvider = userContextProvider; 
    } 

    private readonly IUserContextProvider _userContextProvider; 


    public IStuffModel CreateStuffModel() 
    { 
     String userName = this._userContextProvider.UserName; 
     // do things with userName 
    } 
} 

和登記IUserContextProvider依賴性:

builder.RegisterType<ConcreteStuffFactory>() 
     .As<IStuffFactory>(); 
builder.RegisterType<HttpContextUserContextProvider>() 
     .As<IUserContextProvider>() 
     .InstancePerRequest(); 
builder.Register(c => c.Resolve<IStuffFactory>().CreateStuffModel()) 
     .As<IStuffModel>() 
     .InstancePerRequest(); 
+0

我知道我可以俯瞰這樣一個簡單的解決方案。謝謝!至於'Helper':完全有效的評論,只是重構了代碼庫的舊部分。 –

0

在我看來,你提供的異常文本解釋了爲什麼你的代碼將無法運行。

對我來說,聽起來非常明顯,它不可能訪問啓動方法中的每個請求實例,它本身只會在應用程序的生命週期中調用一次。

我會考慮將您的代碼移動到可以在每個請求的基礎上調用它的位置。你有沒有想過編寫一個custom action filter

相關問題