简体   繁体   English

每个Web请求的StructureMap注入

[英]StructureMap injection per web request

I have an ASP.NET Web Api 2 REST service with several controllers. 我有一个带有多个控制器的ASP.NET Web Api 2 REST服务。 Each one of these controllers' constructor has got an ILogger argument which I have to inject with StructureMap. 这些控制器的构造函数中的每一个都有一个ILogger参数,我必须将其与StructureMap一起插入。 Is it possibile to instantiate an ILogger per request, in order to get client's specific informations - such as the IP address - and thus save the log file to a specific path? 是否可以为每个请求实例化一个ILogger,以获取客户端的特定信息(例如IP地址),然后将日志文件保存到特定路径?

This is the code I'm trying to run in the DefaultRegistry, but HttpContext is always null. 这是我试图在DefaultRegistry中运行的代码,但是HttpContext始终为null。 Where am I wrong? 我哪里错了?

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

I'm not an expert on StructureMap but I understand the problem. 我不是StructureMap的专家,但我了解这个问题。 The problem you have is that you use runtime data to build up your object graph. 您遇到的问题是您使用运行时数据来构建对象图。 And injecting runtime data is an anti-pattern . 注入运行时数据是一种反模式

The simple solution here is not to use the HttpContext directly in your composition root but to create a provider which you can use to determine the path in the FileLogger . 这里的简单解决方案不是在组合根目录中直接使用HttpContext ,而是创建一个可用于确定FileLogger路径的提供FileLogger In that case both the FileLogger as this new provider can become singleton, which is far easier to work with and understand. 在这种情况下,作为该新提供程序的FileLogger都可以成为单例,这更容易使用和理解。

A provider could be as simple as (c#6 syntax): 提供程序可以很简单(c#6语法):

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

Your FileLogger can use this provider as follows: 您的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;
}

I'm not an structuremap user but I think the registration should be: 我不是结构图用户,但我认为注册应该是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM