前期思考:

  1. Microsoft.Logging 是否可用?

  2. 是否需要提供默认的 Logger 实现? 不需要。1,用户自己开启日志功能,设置开启属性,即可打印出相应的日志。

LibLog 类库分析:

类库设计方只需要安装好相应的包,然后在自己的日志类中 添加如下字段。

private static readonly ILog logger = LogProvider.GetCurrentClassLogger()

或者

private static readonly ILog Logger = LogProvider.For<YOUR_CLASS>()

无需安装其他第三方的类库,在记录日志时,只需调用 logger.Info 或者 logger.Error 这时类库的设计就算完成了。当然类库设计方可以提供给客户端一个接口假设为 EnableLogger()

客户端上,用户只需调用这个接口,即可实现类库日志的自动记录,而无需多余操作。

这里面实现的原理是什么,在客户端侧,除了调用类库的一个开启日志功能的接口,其他没有任何操作。

其实可以分析一下我们集成时的类库设计,首先是初始化 Logger 对象

// GetCurrentClassLogger
static ILog GetCurrentClassLogger()
{
var stackFrame = new StackFrame(1, false);
return GetLogger(stackFrame.GetMethod().DeclaringType);
}

获取当前类的日志, 初始化一个 StackFrame,这个应该是 Call Stack 中的Record Frame。下面给出官网上的描述:

A StackFrame is created and pushed on the call stack for every function call made during the execution of a thread.

然后进行 GetLogger()

static ILog GetLogger(string name)
{
var logProvider = CurrentLogProvider ?? ResolveLogProvider();
return logProvider == null
? NoOpLogger.Instance
: (ILog)new LoggerExecutionWrapper(logProvider.GetLogger(name), () => IsDisabled);
}

重点关注 ResolveLogProvider 的这个方法,首先是用到了 Lazy Initialization

private static readonly Lazy ResolvedLogProvider = new Lazy(ForceResolveLogProvider);

然后关注这个 ForceResolveLogProvider,Lazy 方法接收的参数类型为 Func 的委托类型,也就是说,接收一个返回值为 ILogProvider 的方法。

internal static ILogProvider ForceResolveLogProvider()
{
try
{
foreach (var providerResolver in LogProviderResolvers)
{
if (providerResolver.Item1())
{
return providerResolver.Item2();
}
}
}
catch (Exception ex)
{
Console.WriteLine(
"Exception occurred resolving a log provider. Logging for this assembly {0} is disabled. {1}",
typeof(LogProvider).Assembly.FullName,
ex);
}
return null;
}

该方法主要是查找当前进程中是否已经初始化某个日志类了,如果有,则放回这个类。若没有,则抛出异常。重点关注的是 LogProviderResolvers ,这是一个元祖类型 ,定义如下:

static readonly List<Tuple<IsLoggerAvailable, CreateLogProvider>> LogProviderResolvers =
new List<Tuple<IsLoggerAvailable, CreateLogProvider>>
{
new Tuple<IsLoggerAvailable, CreateLogProvider>(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()),
new Tuple<IsLoggerAvailable, CreateLogProvider>(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()),
new Tuple<IsLoggerAvailable, CreateLogProvider>(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()),
new Tuple<IsLoggerAvailable, CreateLogProvider>(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()),
};

配置完 Provider 之后,其实类库已经获取到你本地配置的日志类了,当类库中需要打印日志的需求的话,通过反射来找到项目中的日志类,然后初始化来执行相关的操作。

DEMO样例:

类库:https://github.com/doublnt/dotnetcore/blob/master/LibLogSample/CommonLibLog.cs

客户端:https://github.com/doublnt/dotnetcore/blob/master/CSharpFundamental/LibLog/ConsumerLibLog.cs

LibLog 类库 分析的更多相关文章

  1. WindowsPhone自定义控件详解(二) - 模板类库分析

    转自:http://blog.csdn.net/mr_raptor/article/details/7251948 WindowsPhone自定义控件详解(一) - 控件类库分析 上一节主要分析了控件 ...

  2. 【Allwinner ClassA20类库分析】 2.free pascal语法及结构简析

        上一节介绍了Lazarus一般的开发操作流程,对于不熟悉pascal语言的朋友可能看的还是不大明确.不知道pascal代码里都应该包括什么或起什么作用.这回就简单地介绍下语法及代码文件的结构. ...

  3. WindowsPhone自定义控件详解(一) - 控件类库分析

    转自:http://blog.csdn.net/mr_raptor/article/details/7251942 为了让你的应用程序更有个性,我们通常会在WP7开发过程中会自定义自己风格的控件,自定 ...

  4. 【Allwinner ClassA20类库分析】4.GPIO类的使用

        从本节起,開始使用ClassA20类库完毕操作外设的功能,请先在https://github.com/tjCFeng/ClassA20下载ClassA20类库. 封装的目的就是简化操作,试想一 ...

  5. android-plugmgr源代码分析

    android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...

  6. BAT资深工程师 由浅入深分析 Tp5&Tp6底层源码 - 分享

    BAT资深工程师由浅入深分析Tp5&Tp6底层源码 第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的 ...

  7. BAT资深工程师由浅入深分析Tp5&Tp6底层源码☆

    第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的帮助. 第2章 [TP5灵魂]自动加载Loader 深度分析 ...

  8. fir.im Weekly - iOS/Android 应用程序架构解析

    假如问你一个iOS or Android app的架构,你会从哪些方面来说呢? 本期 fir.im Weekly 收集了关于  iOS/Android 开发资源,也加入了一些关于 Web 前端方面的分 ...

  9. C# 爬虫 Jumony html解析

    前言 前几天写了个爬虫,然后认识到了自己的不足.感谢 "倚天照海- -" ,我通过你推荐的文章,意外的发现了html解析的类库——Jumony. 研究了2天,我发现这个东西简单粗暴 ...

随机推荐

  1. 利用shell脚本快速定位日志

    我们平时查日志,在测试环境,日志文件只有几个的情况下,我们可以通过找时间接近的文件然后根据关键词定位报错位置,大不了都查一遍,这都可以忍受.但是在实际的生产环境下,服务器集群部署,每天的日志非常多非常 ...

  2. OpenGL入门1.7:摄像机

    每一个小步骤的源码都放在了Github 的内容为插入注释,可以先跳过 前言 我们已经知道了何为观察矩阵以及如何使用观察矩阵移动场景(我们向后移动了一点) OpenGL本身没有摄像机(Camera)的概 ...

  3. 关于window10更新之后,15.5版本虚拟机不能使用的情况:检测更新版本

    1.用了四五年的虚拟机,最近居然老提示检测更新版本,嗯,我将我的虚拟机由10版本,更新到了15.5版本,这也是网友说的,然而并灭有什么乱弄.window10系统自动更新,自动更新以后虚拟机就打不开了, ...

  4. Web前端——css

    css 推荐的样式编写顺序: Positioning:定位 Box model:盒子模型.大小等 Typographic:文字系列.排印等 Visual:可视化.背景等 Misc:其它混杂模式 居中 ...

  5. 死磕 java同步系列之StampedLock源码解析

    问题 (1)StampedLock是什么? (2)StampedLock具有什么特性? (3)StampedLock是否支持可重入? (4)StampedLock与ReentrantReadWrite ...

  6. ABAP对象-面向对象(转)

    转自:https://www.jianshu.com/p/f847c8f71438 1 面向对象基础 不多赘述何为对象与类.简单回顾一下在面向对象特性. 封装 限定内部资源的可见性 多态 相同名称的方 ...

  7. oracle 利用序列与触发器实现列自增

    实现步骤:先创建序列,后创建触发器 1.创建序列 create sequence 序列名 increment start maxvalue ; 2.创建触发器 create or replace tr ...

  8. Implement Dependent Reference Properties实现依赖引用属性 (EF)

    In this lesson, you will learn how to implement properties whose values can depend on other properti ...

  9. RV32FDQ/RV64RDQ指令集(1)

    Risc-V架构定义了可选的单精度浮点指令(F扩展指令集)和双精度浮点指令(D扩展指令集),以及四精度浮点指令集(Q扩展指令集).Risc-V架构规定:处理器可以选择只实现F扩展指令子集而不支持D扩展 ...

  10. 【转载】Gradle for Android 第五篇( 多模块构建 )

    Android studio不仅允许你为你的app和依赖库创建模块,同时也可为Android wear,Android TV,Google App Engine等创建模块,而这些单独的模块又可以在一个 ...