您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > C/C++/C#

用 C# 实现一个简单的日志框架

时间:2020-12-22 11:24:04  来源:  作者:

在你的 .NET 程序中经常会记录一些日志或者错误,为了实现这个功能,你可能会使用市面上那些现成的日志框架(log4net,nlog ...),当然你也可以设计并开发一个自己的日志框架,在这篇文章中,我将会带你一起如何轻松愉快的创建一个自定义日志框架,并且一步一步的构建这个简单的 logger。

首先,你要知道什么叫 log targets,从字面意思看就是你的日志要输送到哪里?可以假定我们的日志可以输出到: 文件,数据库 或者 windows 日志 中,下面我在 日志框架 中定义一个枚举表示这三个输出地。


    public enum LogTarget
    {
        File, Database, EventLog
    }

构建 logger 类

接下来实现一下 logger 类,我准备定义三个类来表示这三个output,FileLoggerDBLoggerEventLog ,所有的这些类都需要继承基类 LogBase,下面上一下代码展示一下这些类的继承关系。


    public abstract class LogBase
    {
        public abstract void Log(string message);
    }

    public class FileLogger : LogBase
     {
        public string filePath = @”D:IDGLog.txt”;
        public override void Log(string message)
        {
            using (StreamWriter streamWriter = new StreamWriter(filePath))
            {
                streamWriter.WriteLine(message);
                streamWriter.Close();
            }           
        }
    }

    public class DBLogger : LogBase
    {
        string connectionString = string.Empty;
        public override void Log(string message)
        {
            //Code to log data to the database
        }
    }

    public class EventLogger: LogBase
    {
        public override void Log(string message)
        {
            EventLog eventLog = new EventLog(“”);
            eventLog.Source ="IDGEventLog";
            eventLog.WriteEntry(message);
        }
    } 

上面 DBLogger 的 Log 方法我故意没有实现,你可以在学习完本文后自己来实现这一块的逻辑,将日志记录到数据库中。

正如你看到的,上面三个类:FileLogger,EventLog 和 DBLogger 继承了抽象类 LogBase,这个抽象类定义了一个抽象方法 Log(), 这个 Log() 方法中定义了一个 string 类型的参数,这个参数的内容将会被记录到 file 或者 database 或者 windows event 中。

构建 LogHelper 类

现在我们一起来构建一个 LogHelper 类,这个类可以用简单工厂模式,根据参数的不同创建不同的 XXXLogger 子类,用简单工厂简化我们调用其中各个子类的 Log() 方法,下面展示了具体代码:


    public static class LogHelper
    {
        private static LogBase logger = null;
        public static void Log(LogTarget target, string message)
        {
            switch(target)
            {
                case LogTarget.File:
                    logger = new FileLogger();
                    logger.Log(message);
                    break;
                case LogTarget.Database:
                    logger = new DBLogger();
                    logger.Log(message);
                    break;
                case LogTarget.EventLog:
                    logger = new EventLogger();
                    logger.Log(message);
                    break;
                default:
                    return;
            }
        }
    }

LogHelper 类的 Log() 方法接收一个 string 参数和一个 LogTarget 枚举实例,然后使用 switch: case 结构去决定记录日志的 target 是哪一个。

Log 方法的同步调用

我去,我忘了使用同步机制对这些子类的 log() 方法的调用,现在赶紧同步一下,我可以使用 C# 中的 lock 关键词 在 各个子类的 log 方法的合适地方使用,可以参考下面代码的 LogBase 类,我在这个类中定义了一个 protected 类型的 lockObj 对象,这个对象会被所有子类中的 Log 方法所使用,下面就是这个类的修改版本:


    public abstract class LogBase
    {
        protected readonly object lockObj = new object();
        public abstract void Log(string message);
    }

    public class FileLogger : LogBase
    {
        public string filePath = @”D:IDGLog.txt”;
        public override void Log(string message)
        {
            lock (lockObj)
            {
                using (StreamWriter streamWriter = new StreamWriter(filePath))
                {
                    streamWriter.WriteLine(message);
                    streamWriter.Close();
                }
            }
        }
    }

    public class EventLogger : LogBase
    {
        public override void Log(string message)
        {
            lock (lockObj)
            {
                EventLog m_EventLog = new EventLog(“”);
                m_EventLog.Source ="IDGEventLog";
                m_EventLog.WriteEntry(message);
            }
        }
    }

    public class DBLogger : LogBase
    {
        string connectionString = string.Empty;
        public override void Log(string message)
        {
            lock (lockObj)
            {
                //Code to log data to the database
            }
        }
    }

现在你可以调用 LogHelper.Log 方法了,指定一个 LogTarget 枚举参数和一个需要记录到日志的文本,如下代码所示:


    class Program
    {
        static void Main(string[] args)
        {
            LogHelper.Log(LogTarget.File, “Hello”);
        }
    }

如果你需要切换日志的记录方式,实现起来很简单,在 LogHelper.Log 方法中传递一个不同的 LogTarget 参数即可。

这个框架做的非常简单,还有太多需要实现的功能去完善这个 logger framework,比如说,你可以加入 异步 和 队列,以便应对有大量的 message 被灌入,因为有了异步,logger 在写入日志的时候不会被当前线程阻塞,同样,你也可以实现一些 message 的级别,比如说 info,warning,error 等等。



Tags:C#   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
一、简介很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的。所以我把自己整理的校验帮助类分...【详细内容】
2021-12-27  Tags: C#  点击:(1)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  Tags: C#  点击:(21)  评论:(0)  加入收藏
一文看懂"async"和“await”关键词是如何简化了C#中多线程的开发过程当我们使用需要长时间运行的方法(即,用于读取大文件或从网络下载大量资源)时,在同步的应用程序中,应用程序本...【详细内容】
2021-12-01  Tags: C#  点击:(23)  评论:(0)  加入收藏
OpenCV(Open Source Computer Vision Library)是一个(开源免费)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android、ios等操作系统上,它轻量级而且高效---由一系列...【详细内容】
2021-11-11  Tags: C#  点击:(50)  评论:(0)  加入收藏
在进行C#接口开发时经常需要将数据集转换成json返回,下面介绍一种将DataTable数据转换成实体类,然后再转换成json的方法。一、创建全病案类/// <summary> /// 全病案 //...【详细内容】
2021-11-04  Tags: C#  点击:(44)  评论:(0)  加入收藏
C# 获取网络路径文件大小信息的方法private void button1_Click(object sender, EventArgs e){label2.Text= GetInfo(textBox1.Text);}private string GetInfo(string URL){...【详细内容】
2021-10-29  Tags: C#  点击:(52)  评论:(0)  加入收藏
现如今二维码广泛应用,已经成为了生活中不可或缺的东西;所以我们日常的开发中,也少不了对二维码的生成或者解析。此文讲述一下使用C# 生成和解析二维码 实现功能:将字符串生成二...【详细内容】
2021-10-21  Tags: C#  点击:(58)  评论:(0)  加入收藏
最开始接触.net大概是2003年,当时用的还是framework1.1,那是CAM项目,使用.net主要是利用RemotingService做分布式开发,我当时做其中的一个子系统,因为之前一直都是C++开发,对C#一...【详细内容】
2021-08-17  Tags: C#  点击:(102)  评论:(0)  加入收藏
最近想自己做个录屏工具玩玩,使用的是ffmpeg,录屏是没有问题,在取麦克风及电脑声卡遇到了难题,ffmpeg也可以获取到设备名称但是没办法解析 ( 指令:ffmpeg -list_devices true -f d...【详细内容】
2021-08-04  Tags: C#  点击:(277)  评论:(0)  加入收藏
在实际的项目开发中,可能需要考虑代码的安全性或执行效率,需要将具体的功能实现隐藏,dll接口提供了很好的解决方案。dll接口不仅在C++的项目中可以直接调用,在C#开发的项目也同...【详细内容】
2021-07-09  Tags: C#  点击:(122)  评论:(0)  加入收藏
▌简易百科推荐
一、简介很多时候我们都需要用到一些验证的方法,有时候需要用正则表达式校验数据时,往往需要到网上找很久,结果找到的还不是很符合自己想要的。所以我把自己整理的校验帮助类分...【详细内容】
2021-12-27  中年农码工    Tags:C#   点击:(1)  评论:(0)  加入收藏
引言在学习C语言或者其他编程语言的时候,我们编写的一个程序代码,基本都是在屏幕上打印出 hello world ,开始步入编程世(深)界(坑)的。C 语言版本的 hello world 代码:#include <std...【详细内容】
2021-12-21  一起学嵌入式    Tags:C 语言   点击:(10)  评论:(0)  加入收藏
读取SQLite数据库,就是读取一个路径\\192.168.100.**\position\db.sqlite下的文件<startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0"/...【详细内容】
2021-12-16  今朝我的奋斗    Tags:c#   点击:(21)  评论:(0)  加入收藏
什么是shellshell是c语言编写的程序,它在用户和操作系统之间架起了一座桥梁,用户可以通过这个桥梁访问操作系统内核服务。 它既是一种命令语言,同时也是一种程序设计语言,你可以...【详细内容】
2021-12-16  梦回故里归来    Tags:shell脚本   点击:(16)  评论:(0)  加入收藏
一、编程语言1.根据熟悉的语言,谈谈两种语言的区别?主要浅谈下C/C++和PHP语言的区别:1)PHP弱类型语言,一种脚本语言,对数据的类型不要求过多,较多的应用于Web应用开发,现在好多互...【详细内容】
2021-12-15  linux上的码农    Tags:c/c++   点击:(17)  评论:(0)  加入收藏
1.字符串数组+初始化char s1[]="array"; //字符数组char s2[6]="array"; //数组长度=字符串长度+1,因为字符串末尾会自动添&lsquo;\0&lsquo;printf("%s,%c\n",s1,s2[2]);...【详细内容】
2021-12-08  灯-灯灯    Tags:C语言   点击:(46)  评论:(0)  加入收藏
函数调用约定(Calling Convention),是一个重要的基础概念,用来规定调用者和被调用者是如何传递参数的,既调用者如何将参数按照什么样的规范传递给被调用者。在参数传递中,有两个很...【详细内容】
2021-11-30  小智雅汇    Tags:函数   点击:(19)  评论:(0)  加入收藏
一、问题提出问题:把m个苹果放入n个盘子中,允许有的盘子为空,共有多少种方法?注:5,1,1和1 5 1属同一种方法m,n均小于10二、算法分析设f(m,n) 为m个苹果,n个盘子的放法数目,则先对...【详细内容】
2021-11-17  C语言编程    Tags:C语言   点击:(46)  评论:(0)  加入收藏
一、为什么需要使用内存池在C/C++中我们通常使用malloc,free或new,delete来动态分配内存。一方面,因为这些函数涉及到了系统调用,所以频繁的调用必然会导致程序性能的损耗;另一...【详细内容】
2021-11-17  深度Linux    Tags:C++   点击:(37)  评论:(0)  加入收藏
OpenCV(Open Source Computer Vision Library)是一个(开源免费)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android、ios等操作系统上,它轻量级而且高效---由一系列...【详细内容】
2021-11-11  zls315    Tags:C#   点击:(50)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条