LibLog 类库 分析
前期思考:
Microsoft.Logging 是否可用?
是否需要提供默认的 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 类库 分析的更多相关文章
- WindowsPhone自定义控件详解(二) - 模板类库分析
转自:http://blog.csdn.net/mr_raptor/article/details/7251948 WindowsPhone自定义控件详解(一) - 控件类库分析 上一节主要分析了控件 ...
- 【Allwinner ClassA20类库分析】 2.free pascal语法及结构简析
上一节介绍了Lazarus一般的开发操作流程,对于不熟悉pascal语言的朋友可能看的还是不大明确.不知道pascal代码里都应该包括什么或起什么作用.这回就简单地介绍下语法及代码文件的结构. ...
- WindowsPhone自定义控件详解(一) - 控件类库分析
转自:http://blog.csdn.net/mr_raptor/article/details/7251942 为了让你的应用程序更有个性,我们通常会在WP7开发过程中会自定义自己风格的控件,自定 ...
- 【Allwinner ClassA20类库分析】4.GPIO类的使用
从本节起,開始使用ClassA20类库完毕操作外设的功能,请先在https://github.com/tjCFeng/ClassA20下载ClassA20类库. 封装的目的就是简化操作,试想一 ...
- android-plugmgr源代码分析
android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...
- BAT资深工程师 由浅入深分析 Tp5&Tp6底层源码 - 分享
BAT资深工程师由浅入深分析Tp5&Tp6底层源码 第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的 ...
- BAT资深工程师由浅入深分析Tp5&Tp6底层源码☆
第1章 课程简介 本章主要让大家知道本套课程的主线, 导学内容,如何学习源码等,看完本章要让小伙伴觉得这个是必须要掌握的,并且对加薪有很大的帮助. 第2章 [TP5灵魂]自动加载Loader 深度分析 ...
- fir.im Weekly - iOS/Android 应用程序架构解析
假如问你一个iOS or Android app的架构,你会从哪些方面来说呢? 本期 fir.im Weekly 收集了关于 iOS/Android 开发资源,也加入了一些关于 Web 前端方面的分 ...
- C# 爬虫 Jumony html解析
前言 前几天写了个爬虫,然后认识到了自己的不足.感谢 "倚天照海- -" ,我通过你推荐的文章,意外的发现了html解析的类库——Jumony. 研究了2天,我发现这个东西简单粗暴 ...
随机推荐
- Spring框架的相关介绍
Spring是一个开源轻量级的框架,它的核心是控制反转(IOC)和面向切面编程(AOP). 作为业务层框架的spring能够很好地整合表现层跟持久层. IOC:将类的创建和依赖关系写到配置文件里,可以 ...
- 教妹学 Java:动态伴侣 Groovy
00.故事的起源 “二哥,听说上一篇<多线程>被 CSDN 创始人蒋涛点赞了?”三妹对她提议的<教妹学 Java>专栏一直很关心. “嗯,有点激动.刚开始还以为是个马甲,没 ...
- rxJava2.x源码解析
一. Rxjava是什么 Rxjava在GitHub的介绍是 "A library for composing asynchronous and event-based programs u ...
- 使用pytorch时所遇到的问题总结
使用pytorch时所遇到的问题总结 1.ubuntu vscode切换虚拟环境 在ubuntu系统上,配置工作区文件夹所使用的虚拟环境.之前笔者误以为只需要在vscode内置的终端上将虚拟环境切换过 ...
- Python中文件操作2——shutil模块
1 文件操作 文件有很多的操作,之前的文件操作中介绍了内建函数对文件的打开.读取以及写入,这三种操作是对文件基本的使用.文件还有复制.删除.移动.改变文件的属主属组等操作.下面主要看os模块和shut ...
- CAD画三维图怎么渲染?一分钟教你快速操作
从事过CAD相关工作的都知道,CAD绘制的方式有二维平面图以及三维图形,三维图形,画三维图方式也是比较简单的.那当然三维图画完后一般还需要进行渲染操作,步骤也是比较简洁的.下面就来给大家操作一下CAD ...
- git 多账户链接不同gitlab仓库
1.若之前对 git 设置过全局的 user.name 和 user.email.类似(用git config --global --list 进行查看你是否设置) 一定要清除之前设置的用户和邮箱 $ ...
- PHP mysqli_kill MySQLi 函数
mysqli_kill - 让服务器杀掉一个 MySQL 线程 语法:mysqli_kill ( mysqli $link , int $processid ) 本函数可以用来让服务器杀掉 proce ...
- QML::基本属性类型
QML基本属性类型
- DYNAMICS 365发布所有时候报错:appmodule With Id = a7a513b1-c87d-e911-a83a-000d3a375321 Does Not Exist
我是微软Dynamcis 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...