我使用log4net,并且自定义logg facade几乎与log4net.ILog相同以访问它。 我想记录一个简单的文本文件,但也使用自定义XML appender将内容写入XML。
现在问题就在这里。说我做了像
这样的事情interface IMyILogFacade
{
// An implementation of this interface will eventually route this call to
// log4net.ILogger.Trace
void Trace(string format, params object[] args);
}
class Test
{
IMyILogFacade log; // assume this is given (injected)
public void testMethod(Assembly assembly)
{
string msg = "Entering Method 'testMethod'. Method Parameter 0 (assembly): {0}";
log.Trace(msg, assembly);
}
}
默认情况下,当以任何转换模式或RenderedMessage显式访问%message时,log4net将使用简单的String.Format(msg,assembly)呈现消息。
此行为适用于我的文本文件日志。但是对于我的XML日志,我希望它以不同的方式呈现。简而言之,我想反思参数(程序集)的运行时类型,并转储其所有公共成员及其公共成员'公共成员,等等...到嵌套的XML结构。因此,我不需要使用String.Format(msg,assembly)进行渲染,而是需要使用其他东西,比如String.Format(msg,MyXmlDumper.Dump(assembly))。
我还没有找到任何好的方法来制作渲染,具体取决于Appender的类型。
我目前的做法是让我的记录器外观将所有对Trace,Debug等的调用转换为LogMessage类型的对象。
public class LogMessage
{
public string message { get; protected set; }
public object[] @params { get; protected set; }
public LogMessage(string message, params object[] @params)
{
this.message = message;
this.@params = @params;
}
}
然后我使用一个实现IObjectRenderer的类来渲染它。这将是一个类似ToString的简单函数
public class LogMessageStringRenderer : IObjectRenderer
{
public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
{
LogMessage logMessage = obj as LogMessage;
if(logMessage == null)
{
throw new InvalidOperationException("LogMessageStringRenderer can only render objects of type LogMessage");
} else
{
writer.Write(
String.Format(logMessage.message, logMessage.@params)
);
}
}
}
当然,创建Xml转储时可以直接创建它。
这似乎是一个不太理想的解决方案。首先,这些渲染器(据我所知)只能附加到log4net存储库。通过代码或在配置文件中作为根元素,如
<renderer renderedClass="LogMessage" RenderingClass="LogMessageStringRenderer"/>
但这意味着我必须在我的应用程序中创建两个日志记录库;一个用于文本文件appender,另一个用于xml appender,并相应地设置它们的渲染对象。
这看起来非常复杂(不过我不知道如何最好地使用日志记录库)。
这个问题可能有更好的解决方案吗?也许可以某种方式以appender为基础而不是整个存储库选择渲染器。或者在概念上完全不同的解决方案我还没有。
任何指针都会非常感激。
由于
答案 0 :(得分:0)
经典,一整天都花在这上面,在发布这里之后我找到了解决方案......
我将把我的消息包装在上面发布的LogMessage类中。然后我将创建一个从PatternLayoutConverter转换的派生并将其应用于消息参数:
<param name="ConversionPattern" value="%date	-	%thread	-	%level	-	%-80logger	-	%-40method	-	%message%newline" />
<footer value=" "/>
<converter>
<name value="message" />
<type value="MyMessageConverter"/>
</converter>
如果我很懒,我可能会创建两个转换器,一个用于ToString实现,一个用于基于Xml的转储。 如果我更有野心,我可以创建一个转换器,允许在log4net.config中应用自定义IObjectRenderer并使用它来呈现消息。然后我的IObjcetRenderer实现可以像我在第一篇文章中所描述的那样转换LogMessage。
这应该都很好用;将在下周实施,如果将来有人正在寻找具体的实施,请给我留言。