.NET NLog 详解 (三) - LayoutRender
这期将NLog Git版本指向2005-06-09,NLog v0.9 released。这个时候的代码结构升级为这样:

和上期的版本相比,最明显的莫过于原先的Appender全套更名为Target。这期让我们来关注LayoutRender相关的实现。
LayoutRender
首先LayoutRender 继承自抽象类LayoutRenderer,并且以属性[LayoutRenderer("threadid")]的方式标注。
[LayoutRenderer("threadid")]
public class ThreadIDLayoutRenderer: LayoutRenderer
LayoutRendererFactory初始化的时候会根据该属性,加载指定程序集下面的所有LayoutRender。
public sealed class LayoutRendererFactory
{
private static TypeDictionary _targets = new TypeDictionary();
static LayoutRendererFactory()
{
Clear();
AddDefaultLayoutRenderers();
}
可以看到静态构造函数里面加载默认Renderers。
private static void AddDefaultLayoutRenderers()
{
AddLayoutRenderersFromAssembly(typeof(LayoutRendererFactory).Assembly, String.Empty);
}
public static void AddLayoutRenderersFromAssembly(Assembly theAssembly, string prefix)
{
InternalLogger.Debug("AddLayoutRenderersFromAssembly('{0}')", theAssembly.FullName);
foreach (Type t in theAssembly.GetTypes())
{
LayoutRendererAttribute[]attributes = (LayoutRendererAttribute[])t.GetCustomAttributes(typeof(LayoutRendererAttribute), false);
if (attributes != null)
{
foreach (LayoutRendererAttribute attr in attributes)
{
AddLayoutRenderer(prefix + attr.FormatString, t);
}
}
}
}
下一步就是解析配置文件中的Layout,一般包含Layout 的配置文件是这样子的:
<nlog>
<targets><target name='debug' type='Debug' layout='${basedir} ${message}' /></targets>
<rules>
<logger name='*' minlevel='Debug' appendTo='debug' />
</rules>
</nlog>
这里的layout字符串是: ${basedir} ${message},我们希望得到两个Render的数组。
这里layout.cs 里面有个关键的方法
private static LayoutRenderer[] CompileLayout(string s, out int needsStackTrace)
{
ArrayList result = new ArrayList();
needsStackTrace = 0;
int startingPos = 0;
int pos = s.IndexOf("${", startingPos);
while (pos >= 0)
{
if (pos != startingPos)
{
result.Add(new LiteralLayoutRenderer(s.Substring(startingPos, pos - startingPos)));
}
int pos2 = s.IndexOf("}", pos + 2);
if (pos2 >= 0)
{
startingPos = pos2 + 1;
string item = s.Substring(pos + 2, pos2 - pos - 2);
int paramPos = item.IndexOf(':');
string LayoutRenderer = item;
string LayoutRendererParams = null;
if (paramPos >= 0)
{
LayoutRendererParams = LayoutRenderer.Substring(paramPos + 1);
LayoutRenderer = LayoutRenderer.Substring(0, paramPos);
}
LayoutRenderer newLayoutRenderer = LayoutRendererFactory.CreateLayoutRenderer(LayoutRenderer, LayoutRendererParams);
在这个版本中,采取的是简单粗暴的截取字符串的方式。当需要的Render不存在的时候,创建的是LiteralLayoutRenderer。当存在的时候,存放在数组里返回。
LiteralLayoutRenderer本身不做什么格式化输出,只是简单的返回当前模板的值。
protected internal override int GetEstimatedBufferSize(LogEventInfo ev)
{
return _txt.Length;
}
/// <summary>
/// Renders the specified string literal and appends it to the specified <see cref="StringBuilder" />.
/// </summary>
/// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
/// <param name="ev">Logging event.</param>
protected internal override void Append(StringBuilder builder, LogEventInfo ev)
{
builder.Append(_txt);
}
最后就是Render的输出了。相比于第一思维的直接string.Replace,走了一圈Render的方式更加的安全。
StringBuilder builder = new StringBuilder(size);
for (int i = 0; i < _LayoutRenderers.Length; ++i)
{
LayoutRenderer app = _LayoutRenderers[i];
try
{
app.Append(builder, ev);
}
catch (Exception ex)
{
if (InternalLogger.IsWarnEnabled)
{
InternalLogger.Warn("Exception in {0}.Append(): {1}.", app.GetType().FullName, ex);
}
}
}
return builder.ToString();
这里有一个比较小的注意点,就是StringBuilder初始化的时候指定一个预估的容量size,可以较少性能损失。
.NET NLog 详解 (三) - LayoutRender的更多相关文章
- .NET DLL 保护措施详解(三)最终效果
针对.NET DLL 保护措施详解所述思路完成最终的实现,以下为程序包下载地址 下载 注意: 运行环境为.net4.0,需要安装VS2015 C++可发行组件包vc_redist.x86.exe.然后 ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- WebSocket安卓客户端实现详解(三)–服务端主动通知
WebSocket安卓客户端实现详解(三)–服务端主动通知 本篇依旧是接着上一篇继续扩展,还没看过之前博客的小伙伴,这里附上前几篇地址 WebSocket安卓客户端实现详解(一)–连接建立与重连 We ...
- logback -- 配置详解 -- 三 -- <encoder>
附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...
- python设计模式之装饰器详解(三)
python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...
- Python操作redis字符串(String)详解 (三)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...
- pika详解(三)SelectConnection及其他Connection
pika详解(三)SelectConnection及其他Connection 本文链接:https://blog.csdn.net/comprel/article/details/94661147 ...
- View绘制详解(三),扒一扒View的测量过程
所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...
- Android WebView 开发详解(三)
转载请注明出处 http://blog.csdn.net/typename/article/details/40302351 powered by miechal zhao 概览 Android ...
随机推荐
- python wraps
用代码说明问题: def d(f): def _d(*args, **kwargs): print f.__name__, ' is called' f(*args, **kwargs) return ...
- C# 基于json通讯中的中文的处理
如果通讯中产生了\\u4e00-\\u9fa5范围的中文的unicode代码,而不是\u4e00-\u9fa5范围的,那么c#的处理就比较麻烦了. 破解方法: 机制 它会把\\u4e00拆成部分来识别 ...
- Centos6一键搭建L2TP VPN服务器
用VPS在墙上打洞还有一种叫L2TP,也是常见的一种方式.本脚本结合了L2TP(Layer Tunneling Protocol)和IPSec(Internet Protocol Security), ...
- 【GoLang】GoLang 错误处理 -- 官方推荐方式 示例
最严谨的方式,Always检查error,并做相应的处理 项目结构: 代码: common.go: package common import ( "github.com/pkg/error ...
- 转: UAC 问题
打开VS2005.VS2008.VS2010工程,查看工程文件夹中的Properties文件夹下是否有app.manifest这个文件:如 没有,按如下方式创建:鼠标右击工程在菜单中选择“属性”,点击 ...
- ios coredata 无任何错误提示crash
最近写程序是遇到了一种情况,对coredata 操作时,有一定几率crash,crash时无任何说明,断点调试后发现,fetch出的对象的属性竟然和数据库中的不同,不知道什么情况下导致了context ...
- linux下的audit服务
audit ['ɔːdɪt] 审计 auditd是linux的一个审计服务. 这是man下的解释 auditd is the userspace component to the Linux A ...
- jira与mysql的配合搭建调整
jira与mysql数据的整合 第一步:电脑上安装mysql数据库,不做多得解释,自己搞定 第二步: 在mysql数据库中建一个名为 jiradb的数据库,账号 root 密码 root 编码格式 u ...
- ffmpeg-20160628-git-bin.7z
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...
- [Android]检查当前手机是否有网络
// Check network connection private boolean isNetworkConnected(){ ConnectivityManager connectivityMa ...