我有一个带有多个控制器的ASP.NET Web Api 2 REST服务。这些控制器中的每一个都是'构造函数有一个ILogger参数,我必须使用StructureMap注入。是否有可能为每个请求实例化ILogger,以获取客户端的特定信息(例如IP地址),从而将日志文件保存到特定路径?
这是我尝试在DefaultRegistry中运行的代码,但HttpContext始终为null。我哪里错了?
For<ILogger>()
.Use(() => new TextFileLogger(
HttpContext.Current.Request.UserHostAddress +
DirectorySeparatorChar + "log.txt"));
答案 0 :(得分: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;
}
我不是结构图用户,但我认为注册应该是:
For<ILogFileProvider>.Use<HttpLogfileProvider>.Singleton;
For<ILogger>.Use<FileLogger>.Singleton;