2016-05-13 17 views
0

我有一個ASP.NET Web Api 2 REST服務與幾個控制器。這些控制器的每個構造函數都有一個ILogger參數,我必須用StructureMap注入。是否有可能爲每個請求實例化一個ILogger,以便獲取客戶端的特定信息(如IP地址)並將日誌文件保存到特定路徑?每個Web請求的結構映射注入

這是我試圖在DefaultRegistry中運行的代碼,但HttpContext始終爲空。我錯在哪裏?

For<ILogger>() 
    .Use(() => new TextFileLogger(
     HttpContext.Current.Request.UserHostAddress + 
     DirectorySeparatorChar + "log.txt")); 

回答

4

我不是StructureMap的專家,但我理解這個問題。您遇到的問題是您使用運行時數據來構建對象圖。和injecting runtime data is an anti-pattern

這裏的簡單解決方案不是直接在組合根中使用HttpContext,而是創建一個提供程序,您可以使用該提供程序來確定FileLogger中的路徑。在這種情況下,作爲這個新提供者的FileLogger都可以變成單身人士,這更容易處理和理解。

提供者可能是爲(C#語法6)一樣簡單:

public class HttpLogfileProvider : ILogFileProvider 
{ 
    public string PathToLogfile => 
     Path.Combine(HttpContext.Current.Request.UserHostAddress, "log.txt"); 
} 

FileLogger可以按如下方式使用此提供程序:

public class FileLogger : ILogger 
{ 
    private readonly ILogFileProvider logFileProvider; 
    public FileLogger(ILogFileProvider logFileProvider) 
    { 
     this.logFileProvider = logFileProvider; 
    } 

    public void Log(string message) 
    { 
     using (var writer = new StreamWriter(this.currentLogFile)) 
     { 
       writer.WriteLine(message); 
     } 
    } 

    private string currentLogFile => 
     this.logFileProvider.PathToLogFile; 
} 

我不是一個structuremap用戶,但我認爲註冊應該是:

For<ILogFileProvider>.Use<HttpLogfileProvider>.Singleton; 
For<ILogger>.Use<FileLogger>.Singleton; 
+0

真的謝謝你,男人。我是新來的依賴注入,這些信息對我來說是純金! –