我想将现有代码从.NET 4.7.2/log4net迁移到最新的.NET Core版本(当前为2.2,到9月应该是3.0(和"默认"日志记录。
我们有很多行代码来获取类MyClass
的log4net Logger实例,例如:
private static ILog _logger = LogManager.GetLogger(typeof(MyClass));
并像_logger.Info("Some message");
一样使用记录器
我找到的大多数示例和文档都在类构造函数中使用依赖注入,例如:
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
记录器是这样使用的:
_logger.LogInformation("Message displayed: {Message}", Message);
对我来说,迁移的最大问题是它是由构造函数中的 DI 传递的,这可能很好,就像在 MVC 控制器的例子中一样,但在我遇到的其他几个类中存在问题,因为破坏了构造函数的签名。
我正在寻找一个不会破坏构造函数签名的实现(例如 Xamarin 中的 DI,这将使迁移过程更容易( - 类似于:
private static ILogger _logger = DependencyService.Get<ILogger<MyClass>>();
到目前为止,我发现的是在他们使用HttpContext.RequestServices的 http://www.binaryintellect.net/articles/17ee0ba2-99bb-47f0-ab18-f4fc32f476f8.aspx 的例子:
INotificationHelper helper = (INotificationHelper) HttpContext.RequestServices.GetService(typeof(INotificationHelper));
我的代码也在控制台应用程序中运行,因此在这些情况下我没有 HttpContext。知道如何用.NET Core解决这个问题吗?(最好没有任何第三方库(。请注意,我不仅要迁移一个类,最多可能有 1000 个类。
我知道你说最好没有第三方库,但我认为你会发现这个非常有用。它是Microsoft.Extensions.Logging.Log4net.AspNetCore。 下面是如何使用它的示例
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using System.IO;
using System.Reflection;
namespace TryLog4net
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
var assembly = Assembly.GetAssembly(typeof(Program));
var pathToConfig = Path.Combine(
hostingContext.HostingEnvironment.ContentRootPath
, "log4net.config");
var logManager = new AppLogManager(pathToConfig, assembly);
logging.AddLog4Net(new Log4NetProviderOptions
{
ExternalConfigurationSetup = true
});
})
.UseStartup<Startup>();
}
}
在项目的根目录中放置您的 log4net.config 文件。 一个例子是
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="DebugAppender" type="log4net.Appender.DebugAppender" >
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="DebugAppender" />
</root>
</log4net>
这是一种无需按照要求使用依赖注入即可获取记录器的方法。
using log4net;
using System;
using System.IO;
using System.Reflection;
namespace TryLog4net
{
public class AppLogManager
{
private static AppLogManager _logManager = null;
private AppLogManager()
{
}
public AppLogManager(string fullConfigFilePath, Assembly assembly)
{
var logRepo = log4net.LogManager.GetRepository(assembly);
log4net.Config.XmlConfigurator.Configure(logRepo, new FileInfo(fullConfigFilePath));
_logManager = new AppLogManager();
}
public static ILog GetLogger<T>()
{
return _logManager.GetLogger(typeof(T));
}
public ILog GetLogger(Type type)
{
var log = log4net.LogManager.GetLogger(type);
return log;
}
}
public static class GenericLoggingExtensions
{
public static ILog Log<T>(this T thing)
{
var log = AppLogManager.GetLogger<T>();
return log;
}
}
}
下面是一个非常简单的示例启动文件,用于创建日志消息。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace TryLog4net
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async (context) =>
{
var testClass = new TestClass();
testClass.LogSomething();
await context.Response.WriteAsync("Hello World!");
});
}
public class TestClass
{
public void LogSomething()
{
var logger = this.Log();
logger.Info("my message");
}
}
}
}