我正在尝试将Serilog注入到我的.NET Core 3.1 WPF应用程序中的类和项目中。
我正在使用 Caliburn.Micro 框架来处理 MVVM 方面的事情,Serilog Logger 已在 Bootstrapper 类中配置,我不清楚的是我如何注册记录器的实例,以便它可以用于跨我的应用程序的 DI。
这就是我在 Bootstrapper 类中所拥有的,我在构造函数中添加了一个简单的try-catch
来证明记录器已配置。
public class Bootstrapper : BootstrapperBase
{
private SimpleContainer _container = new SimpleContainer();
public Bootstrapper()
{
Initialize();
try
{
Log.Information("In Bootstrapper Configure method");
}
catch (Exception ex)
{
Log.Fatal(ex, "The application failed to start correctly");
}
finally
{
Log.CloseAndFlush();
}
}
protected override void Configure()
{
_container.Instance(_container);
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File("log.txt")
.CreateLogger();
_container
.Singleton<IWindowManager, WindowManager>()
.Singleton<IEventAggregator, EventAggregator>()
_container
.PerRequest<IMyDataHandler, MyDataHandler>();
GetType().Assembly.GetTypes()
.Where(type => type.IsClass)
.Where(type => type.Name.EndsWith("ViewModel"))
.ToList()
.ForEach(viewModelType => _container.RegisterPerRequest(
viewModelType, viewModelType.ToString(), viewModelType));
}
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ShellViewModel>();
}
protected override object GetInstance(Type service, string key)
{
return _container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
}
任何帮助或指向文档的指针都会很棒。
日志是静态的,记录器是静态的,所以不需要注册,也不需要使用 DI:
任何您使用Log.Information("something");
或Log.Fatal("something");
的地方,这些都将进入您的日志文件。
public class SomeViewModel
{
public SomeViewModel()
{
Log.Information("i am in somethingVM");
}
}
之后,如果你想使用 DI,你必须使用这样的实例:(我使用 Caliburn 给出的接口 ILog 并创建封装 Logger 的类 Log。
public class Log : ILog
{
#region Fields
#endregion
private readonly ILogger logger;
#region Constructors
public Log()
{
logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.File(@"d:log.txt").CreateLogger();
}
#endregion
#region Helper Methods
private string CreateLogMessage(string format, params object[] args)
{
return string.Format("[{0}] {1}",
DateTime.Now.ToString("o"),
string.Format(format, args));
}
#endregion
#region ILog Members
public void Error(Exception exception)
{
logger.Error(CreateLogMessage(exception.ToString()), "ERROR");
}
public void Info(string format, params object[] args)
{
if (Array.FindIndex(args, t => t.ToString().Contains("Something i dont want to log")) >= 0)
return;
logger.Information(CreateLogMessage(format, args), "INFO");
}
public void Warn(string format, params object[] args)
{
logger.Warning(CreateLogMessage(format, args), "WARN");
}
#endregion
}
并将 ILog 与日志绑定
_container.Singleton<ILog, Log>();
public class SomeViewModel
{
public SomeViewModel(ILog logger)
{
logger.Info("i am in somethingVM");
}
}
我不是 simplecontainer 的专家,但如果您想在引导程序中调用记录器,则必须在像这样注册后将实例捕获在容器中(进行测试(:
IoC.Get<ILog>().Info("I am in boot");
使用这种编程方式,您可以做您想做的事,我已经将类日志与Serilog链接为您的示例,但无需使用它。
我使用 ninject,所以我们可以用它:
kernel.Bind<ILogger>().ToMethod(x => new LoggerConfiguration()
.WriteTo.File(@"d:toto.log")
.CreateLogger());
这简化了绑定,但我不知道 simplecontainer 是否具有此功能,无需声明类 Log。
public class SomeViewModel
{
public SomeViewModel(ILogger logger)
{
logger.Information("i am in somethingVM");
}
}
使用简单容器,我看到了这种语法,但不确定它是否与 Ninject 相同:
Container.RegisterHandler(typeof(ILogger), "Ilogger", x => new LoggerConfiguration()
.WriteTo.File(@"d:log.txt")
.CreateLogger());
你可以注册 Serilog 的ILogger
,就像在应用中注册所有其他单例一样,通过在容器上调用Singleton
:
_container.Singleton<ILogger, Log.Logger>();
在您的应用程序中使用 Serilog 记录器的另一种方法(我个人更喜欢(是从您的任何类(ViewModels、服务等(访问Log.Logger
。使用Log.ForContext<>
的每个类都有一个上下文记录器也很容易,这在解决问题时很有用。例如
public class SomeViewModel
{
private readonly ILogger _log = Log.ForContext<SomeViewModel>();
// ...
}
public class SomeService
{
private readonly ILogger _log = Log.ForContext<SomeService>();
// ...
}