这期将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的更多相关文章

  1. .NET DLL 保护措施详解(三)最终效果

    针对.NET DLL 保护措施详解所述思路完成最终的实现,以下为程序包下载地址 下载 注意: 运行环境为.net4.0,需要安装VS2015 C++可发行组件包vc_redist.x86.exe.然后 ...

  2. Android 之窗口小部件详解(三)  部分转载

    原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...

  3. WebSocket安卓客户端实现详解(三)–服务端主动通知

    WebSocket安卓客户端实现详解(三)–服务端主动通知 本篇依旧是接着上一篇继续扩展,还没看过之前博客的小伙伴,这里附上前几篇地址 WebSocket安卓客户端实现详解(一)–连接建立与重连 We ...

  4. logback -- 配置详解 -- 三 -- <encoder>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  5. python设计模式之装饰器详解(三)

    python的装饰器使用是python语言一个非常重要的部分,装饰器是程序设计模式中装饰模式的具体化,python提供了特殊的语法糖可以非常方便的实现装饰模式. 系列文章 python设计模式之单例模 ...

  6. Python操作redis字符串(String)详解 (三)

    # -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...

  7. pika详解(三)SelectConnection及其他Connection

    pika详解(三)SelectConnection及其他Connection   本文链接:https://blog.csdn.net/comprel/article/details/94661147 ...

  8. View绘制详解(三),扒一扒View的测量过程

    所有东西都是难者不会,会者不难,Android开发中有很多小伙伴觉得自定义View和事件分发或者Binder机制等是难点,其实不然,如果静下心来花点时间把这几个技术点都研究一遍,你会发现其实这些东西都 ...

  9. Android WebView 开发详解(三)

    转载请注明出处   http://blog.csdn.net/typename/article/details/40302351 powered by miechal zhao 概览 Android ...

随机推荐

  1. Weiphp随笔,百度天气API接口

    新建插件名必须大写 http://api.map.baidu.com/telematics/v3/weather?location=%E5%8C%97%E4%BA%AC&output=json ...

  2. phpcms访问顶级栏目,自动跳到第一个子栏目

    在顶级栏目的category页放入如下代码: <?php if($child){ $child_arrary=explode(',',$arrchildid); $to_url=$CATEGOR ...

  3. LINUX优化得很好的sysctl.conf配置

    最近找了个不错的sysctl.conf的优化参数,在网站响应上已经算不错了的,time超时连接据说几乎为0了.  系统:centos 5.x sysctl.conf配置参数: kernel.msgmn ...

  4. [android]如何使LinearLayout布局从右向左水平排列,而不是从左向右排列

    方法1: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:l ...

  5. Debian Vi 简介

    1.Vi 简介    Vi 是 Unix 世界里极为普遍的全萤幕文书编辑器,几乎可以说任何一台  Unix 机器都会提供这套软体.Linux 当然也有,它的 vi 其实是 elvis (版权问题),不 ...

  6. js中 map 遍历数组

    map 方法会迭代数组中的每一个元素,并根据回调函数来处理每一个元素,最后返回一个新数组.注意,这个方法不会改变原始数组. 在我们的例子中,回调函数只有一个参数,即数组中元素的值 (val 参数) , ...

  7. AOP理解

    1.问题 问题:想要添加日志记录.性能监控.安全监测 2.最初解决方案 2.1.最初解决方案 缺点:太多重复代码,且紧耦合 2.2.抽象类进行共性设计,子类进行个性设计,此处不讲解,缺点一荣俱荣,一损 ...

  8. 解析客户端IP

    <html><head><title>新浪IP解析接口的使用</title><metahttp-equiv=Content-Typecontent ...

  9. xcode运行push通知总是提示输入用户名和密码

    xcode运行push通知总是提示输入用户名和密码,目前找到的解决方案是,  打开钥匙串,然后找到push证书下面的私有密钥,双击进入将访问控制设置为允许全部访问,即可.

  10. ajax基础语法、ajax做登录、ajax做用户名验证是否可用、ajax做关键字查询动态显示、ajax做用表格显示数据并增加操作列

    AJAX: AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新.   ...