gpt4 book ai didi

c# - 如何使用 Unity 为 LogManager (NLog) 获取命名记录器

转载 作者:行者123 更新时间:2023-11-30 22:13:26 46 4
gpt4 key购买 nike

这将是一个冗长的问题,但请耐心等待。我正在尝试为我们的应用程序创建一个日志记录组件,它可以扩展为插入新的日志记录框架(NLog、Log4Net ec)。现在我知道我们已经有了由 Ben Foster 编写的 Common.Logging 门面,但我想尝试一些更定制的东西。在我们的案例中,一个主要要求是我们需要一种自定义机制,使用日志记录框架(在本例中为 NLog)将各个参数/值记录到数据库中。所以我有一个简单的日志记录界面:

/// <summary>
/// Interface for implementing a Logger Provider.
/// </summary>
public interface ILogger
{
/// <summary>
/// Logs an Info level diagnostics message.
/// </summary>
/// <param name="logInfo">The Log Info object.</param>
void Info(LogInfo logInfo);

/// <summary>
/// Logs a Warn level diagnostics message.
/// </summary>
/// <param name="logInfo">The Log Info object.</param>
void Warn(LogInfo logInfo);

/// <summary>
/// Logs a Debug level diagnostics message.
/// </summary>
/// <param name="logInfo">The Log Info object.</param>
void Debug(LogInfo logInfo);

/// <summary>
/// Logs an Error level diagnostics message.
/// </summary>
/// <param name="logInfo">The Log Info object.</param>
void Error(LogInfo logInfo);

/// <summary>
/// Logs an Fatal level diagnostics message.
/// </summary>
/// <param name="logInfo">The Log Info object.</param>
void Fatal(LogInfo logInfo);
}

LogInfo 对象包含所有必要的日志记录信息。我有一个实现接口(interface)的抽象类:

public abstract class NLogLoggerBase : ILogger
{
....
}

它被子类化为:

public class NLogDatabaseLogger : NLogLoggerBase
{
public NLogDatabaseLogger(ILogUtility logUtility)
: base(logUtility)
{
//Make sure the custom target is registered for use BEFORE using it.
ConfigurationItemFactory.Default.Targets.RegisterDefinition("DatabaseLog", typeof(DatabaseLogTarget));

//initialize the _logger
_logger = LogManager.GetLogger("DatabaseLogger");
}
}

public class NLogFileLogger : NLogLoggerBase
{
....
}

数据库记录器使用自定义的 DatabaseTarget(继承自 NLog 中的 TargetWithLayout)来登录数据库,文件记录器也是如此。 NLog 的基本设置在 App.Config 中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
</configSections>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true" throwExceptions="false" internalLogFile="C:\Temp\nlog.txt" internalLogLevel="Info"
internalLogToConsole="false">
<targets async="true">
<target name="CustomDatabaseLog" xsi:type="DatabaseLog" />
<target name="CustomFileLog" xsi:type="File" />
</targets>

<rules>
<logger name="DatabaseLogger" minlevel="Info" writeTo="CustomDatabaseLog" />
<logger name="FileLogger" minlevel="Info" writeTo="CustomFileLog" />
</rules>
</nlog>
</configuration>

到目前为止一切顺利。我对每个记录器进行了一些测试,它们可以很好地记录到各自的目标。

然后我写了一个 Logger 工厂,它将根据记录器类型返回 ILogger 接口(interface)的正确实现:

/// <summary>
/// Provides an interface for a factory which returns a logger component.
/// </summary>
public interface ILoggerFactory
{
/// <summary>
/// Creates an instance of logger component based on dependency registration key.
/// </summary>
/// <param name="loggerName">The dependency registration key.</param>
/// <returns>An Instance of logger component.</returns>
ILogger CreateLogger(string loggerName);
}

和实现:

/// <summary>
/// Implementation of ILoggerFactory interface.
/// </summary>
public class NLogLoggerFactory : ILoggerFactory
{
private readonly ILogger _nlogDatabaseLogger;
private readonly ILogger _nlogFileLogger;

public NLogLoggerFactory(ILogger nlogDatabaseLogger, ILogger nlogFileLogger)
{
if (nlogDatabaseLogger == null)
throw new ArgumentNullException("nlogDatabaseLogger");

if (nlogFileLogger == null)
throw new ArgumentNullException("nlogFileLogger");

_nlogDatabaseLogger = nlogDatabaseLogger;
_nlogFileLogger = nlogFileLogger;
}

/// <summary>
/// Creates an instance of logger component based on dependency registration key.
/// </summary>
/// <param name="loggerKey">The dependency registration key.</param>
/// <returns>An Instance of logger component.</returns>
public ILogger CreateLogger(string loggerKey)
{
if (loggerKey.Equals(DependencyRegistrationKeys.NLogDatabaseLoggerKey))
return _nlogDatabaseLogger;

if (loggerKey.Equals(DependencyRegistrationKeys.NLogFileLoggerKey))
return _nlogFileLogger;

throw new ArgumentException("Invalid loggerKey");
}

所以我开始使用 Unity 将其全部连接起来。这是我编写的快速测试用例(我知道它需要重构,但它只是为了说明目的):

    [Test]
public void Test_if_logger_factory_returns_correct_implementation()
{
var container = new UnityContainer();
container.RegisterType<ILogUtility, NLogUtility>();
container.RegisterType<ILogger, NLogDatabaseLogger>(DependencyRegistrationKeys.NLogDatabaseLoggerKey);
container.RegisterType<ILogger, NLogFileLogger>(DependencyRegistrationKeys.NLogFileLoggerKey);
container.RegisterType<ILoggerFactory, NLogLoggerFactory>(
new InjectionConstructor(
new ResolvedParameter<ILogger>(DependencyRegistrationKeys.NLogDatabaseLoggerKey),
new ResolvedParameter<ILogger>(DependencyRegistrationKeys.NLogFileLoggerKey)));

var loggerFactory = container.Resolve<ILoggerFactory>();
Assert.IsAssignableFrom<NLogLoggerFactory>(loggerFactory);

var logger = loggerFactory.CreateLogger(DependencyRegistrationKeys.NLogDatabaseLoggerKey);
Assert.IsNotNull(logger);
Assert.IsAssignableFrom<NLogDatabaseLogger>(logger);
}

一切正常,直到我到达终点:

var loggerFactory = container.Resolve<ILoggerFactory>();

这似乎按预期命中了 NLogDatabaseLogger 的构造函数,并在该行上爆炸并出现异常:

//initialize the _logger
_logger = LogManager.GetLogger("DatabaseLogger");

异常(exception):

Required parameter 'FileName' on 'File Target[CustomFileLog_wrapped]' was not specified.

我的猜测是 Unity 正在努力获取 NLog,以获取命名记录器实例。有没有人遇到过这个?有没有办法解决?我整个上午都在为此苦思冥想,但没有骰子。非常感谢任何帮助!

最佳答案

查看这个问题和我的回答。

How to Inject Log4Net ILog implementations using Unity 2.0

问题是关于使用 unity 解析命名 log4net 记录器,但我认为您应该能够将相同的过程应用于 NLog 和 unity。

该问题的 OP 写了一个 nice blog post描述了他为使它起作用所经历的确切过程。从他的博客文章中,这些是所需的步骤(假设有一些统一知识):

在 Unity 中实现它需要三个步骤。

  1. 创建构建跟踪扩展
  2. 创建记录器创建扩展
  3. 将扩展连接到 Unity

祝你好运!

关于c# - 如何使用 Unity 为 LogManager (NLog) 获取命名记录器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19159473/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com