来自静态类的 ASP.NET Core Web API 日志记录
Posted
技术标签:
【中文标题】来自静态类的 ASP.NET Core Web API 日志记录【英文标题】:ASP.NET Core Web API Logging from a Static Class 【发布时间】:2018-07-18 11:19:43 【问题描述】:我在我的控制器上使用依赖注入记录得很好,现在我需要记录一些来自静态类的东西。
如何从静态类记录?
我不能使用依赖注入,因为它是静态的,而且我不能只将现有的记录器对象传递给静态类,因为它会在日志文件中使用错误的类名。
换句话说,我如何从我的静态类中的 loggerfactory 获取一个记录器?
我遇到了一个类似的问题,他们指出了一篇关于静态类中的 loggerfactory 的文章,但这实际上不起作用,因为我无法从中获取新的记录器,因为它不接受静态类作为参数:
“静态类型不能用作类型参数”
【问题讨论】:
你有没有想过这个问题?我想从扩展方法登录。 解决方案在这里@illug 相关:***.com/q/50712720/11635 【参考方案1】:我在 Startup
类中添加了 ILoggerFactory 的静态成员,因此它可以在其他类中使用。
public class Startup
internal static ILoggerFactory LogFactory get; set;
…
public void Configure(…, ILoggerFactory logFactory)
…
LogFactory = logFactory;
然后在静态类中使用。
static class YourClass
private static ILogger<YourClass> Logger = Startup.LogFactory.CreateLogger<YourClass>();
…
但是,当 CreateLogger 抛出异常时,这段代码会导致 TypeInitializationException,所以你应该尝试做得更好。 [1]
【讨论】:
【参考方案2】:我发现这个问题的答案很有用,但我记得我已经安装了 Serilog。我可以使用 Serilog 的默认实现,而不是实现自定义静态实例。
它带有多个不错的日志记录功能和多个重载版本。 这里有两个例子:
using Serilog;
...
Log.Error(myException, "my message");
Log.Warning("My message", myValue);
Serilog.Log
是一个静态实例,在 Program.cs 或 Startup.cs 中配置后即可使用。
【讨论】:
如果您不需要使用关注点分离原则,您可以在需要时轻松替换日志框架。 是的,如果想在自定义记录器中使用 Serilog,可以让自定义记录器基本上成为 Serilog 的包装器:) 如 OP 所要求的,要绑定到调用类, 可以实现类似 factorymethod 的方法,其类型参数为 @Adrian 所描述的。 您是在编写具体的代码,而不是编写接口。未来的读者,只要“注意”这种情况。【参考方案3】:您可以将静态LoggerFactory
实例与以下扩展方法一起使用,该方法接受Type
类型的常规参数,而不是泛型类型参数:
CreateLogger(ILoggerFactory, Type)
即loggerFactory.CreateLogger(typeof(T))
而不是 loggerFactory.CreateLogger<T>()
【讨论】:
您的意思是“a staticLoggerFactory
instance”吗?除非您设置一个,否则没有可用的静态 LoggerFactory
实例。【参考方案4】:
解决方案是在启动时初始化的实用程序静态类中对 LoggerFactory 进行静态引用:
/// <summary>
/// Shared logger
/// </summary>
internal static class ApplicationLogging
internal static ILoggerFactory LoggerFactory get; set; // = new LoggerFactory();
internal static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();
internal static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger(categoryName);
您在 Startup.cs 上初始化的内容:
public Startup(ILogger<Startup> logger, ILoggerFactory logFactory, IHostingEnvironment hostingEnvironment)
_log = logger;
_hostingEnvironment = hostingEnvironment;
Util.ApplicationLogging.LoggerFactory = logFactory;//<===HERE
然后您可以构建一个记录器以从您的静态类中使用,如下所示:
internal static class CoreJobSweeper
private static ILogger log = Util.ApplicationLogging.CreateLogger("CoreJobSweeper");
【讨论】:
完美!然而,值得添加一个强类型 CreateLogger 的示例,特别是对于我们复制/粘贴爱好者来说只是寻找快速解决问题的方法:) 即 private static ILogger log = Util.ApplicationLogging.CreateLogger首先,我同意NightOwl888 的回答。
但作为一种选择(将其视为一种解决方法),您可以通过方法参数注入 ILogger
依赖项 => 因此将调用此静态方法的类应该负责提供 ILogger
的正确实现。
static class YourClass
public static void DoSomething(ILogger logger)
// do something
// call log.Log();
【讨论】:
Nightowl 根本没有回答这个问题,而是发表了一个不受欢迎的演讲,我在我的问题中专门讨论了你的建议以及为什么我不能这样做。 为了能够在任何地方记录,您必须在数万行代码中强制要求对每个方法/对象的记录器依赖。这对我来说听起来是个可怕的主意。在这种情况下,静态工厂是更明智的选择。以上是关于来自静态类的 ASP.NET Core Web API 日志记录的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core Web API使用静态swagger.json文件
如果参数名称等于属性名称,则来自查询的 ASP.NET Core Web API 复杂类型绑定不起作用
使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API