这期将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. python 内置速度最快算法(堆排)

    import random import time from heapq import heappush, heappop def heapsort(iterable): h = [] for val ...

  2. 17.5---珠玑妙算,四个槽,红色黄色绿色蓝色(CC150)

    思路:注意一下,找猜中的时候什么都不用做,直接统计,找伪猜中也是先不管,然后再把结果减去猜中即可. public static int[] calcResult(String a, String b) ...

  3. 跨域解决方案二:使用JSONP实现跨域

    跨域的实现方式有多种,除了 上篇文章 提到的CORS外,常见的还有JSONP.HTML5.Flash.iframe.xhr2等. 这篇文章对JSONP的跨域原理进行了探索,并将我的心得记录在这里和大家 ...

  4. 【GoLang】GoLang 错误处理 -- 使用异常的思路进行处理

    go处理错误的另一种方式 go处理错误常见的方式是 err := funcReturningError() if err != nil { // 处理错误 } 然而因为过于繁琐而饱受诟病.下文简述另一 ...

  5. MongoDB-Getting Started with the C# Driver

    简介:本文仅提供快速入门级别的使用C# Driver操作MongoDB,高手跳过 Downloading the C# Driver 猛击下载 添加相关的dll引用 MongoDB.Bson.dll ...

  6. Longest Increasing Path in a Matrix

    Given an integer matrix, find the length of the longest increasing path. From each cell, you can eit ...

  7. 【leetcode】Word Ladder II

      Word Ladder II Given two words (start and end), and a dictionary, find all shortest transformation ...

  8. 【leetcode】Next Permutation

    Next Permutation Implement next permutation, which rearranges numbers into the lexicographically nex ...

  9. Android 自动化测试 常用的命令----随时更新

    常用命令分为三类,如下: 1. android android sdk : 打开SDK管理器. android avd : 打开虚拟设备管理器. android --help : 查看帮助信息. 2. ...

  10. ACM/ICPC 之 Prim范例(ZOJ1586-POJ1789(ZOJ2158))

    两道Prim解法范例题型,简单的裸Prim,且两题相较以边为重心的Kruskal解法而言更适合以点为重心扩展的Prim解法. ZOJ1586-QS Network 题意:见Code 题解:直接的MST ...