每个 Web 请求的 StructureMap 注入

StructureMap injection per web request

我有一个带有多个控制器的 ASP.NET Web Api 2 REST 服务。这些控制器的每个构造函数都有一个 ILogger 参数,我必须用 StructureMap 注入它。是否可以为每个请求实例化一个 ILogger,以获取客户端的特定信息(例如 IP 地址),从而将日志文件保存到特定路径?

这是我试图 运行 在 DefaultRegistry 中的代码,但 HttpContext 始终为空。我哪里错了?

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

我不是 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;
}

我不是结构图用户,但我认为注册应该是:

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