C# 赖加载+多线程安全实现日志文件

本文介绍了一个日志管理系统的设计方案,包括文件日志、数据库日志和事件日志等多种类型的实现方式,并提供了一个日志工厂来统一创建不同类型的日志记录器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

优点:懒加载模式,IO流不会重复实例化使用,多线程安全。

日志基类接口

    /// <summary>
    /// 日志基类接口
    /// </summary>
    public interface LogBase:IDisposable
    {
        /// <summary>
        /// 记录信息
        /// </summary>
        /// <param name="message">消息内容</param>
        void LogInfo(string message);
        /// <summary>
        /// 记录警告信息
        /// </summary>
        /// <param name="message">消息内容</param>
        void LogWarning(string message);
        /// <summary>
        /// 记录错误信息
        /// </summary>
        /// <param name="message">消息内容</param>
        void LogError(string message);
    }

FileLogger文件日志类实现LogBase接口

    public class FileLogger<T> : LogBase where T : class, new()
    {
        private StreamWriter streamWriter;
        private string _filePath;
        private bool _disposed;
        private string _className;
        private static Lazy<FileLogger<T>> lazy;
        private Object writerLock = new Object();

        private FileLogger(string filePath, string className)
        {
            if (string.IsNullOrEmpty(filePath))
                return;

            _filePath = filePath;
            _className = className;

            string path = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            // 不覆盖
            streamWriter = new StreamWriter(filePath,true);
        }
        public static FileLogger<T> GetInstance(string path = null)
        {
            if (path == null)
                path = System.Environment.CurrentDirectory + "\\Log\\"+ DateTime.Now.ToString("yyyyMMdd")+"\\" + DateTime.Now.ToString("yyyyMMddHH") + ".txt";

            lazy = new Lazy<FileLogger<T>>(() =>
            {

                return new FileLogger<T>(path, typeof(T).Name);
            });

            return lazy.Value;
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            lock (writerLock)
            {
                if (!_disposed)
                {
                    if (disposing)
                    {
                        // Release managed resources
                        _filePath = null;
                        _className = null;
                    }

                    // Release unmanaged resources
                    streamWriter.Close();
                    streamWriter.Dispose();

                    _disposed = true;
                }
            }
        }
        public void LogInfo(string message)
        {
            Write("LogInfo", message, _className);
        }

        public void LogWarning(string message)
        {
            Write("LogWarning", message, _className);
        }

        public void LogError(string message)
        {
            Write("LogError", message, _className);
        }
        /// <summary>
        /// 写入消息方法
        /// </summary>
        /// <param name="mesType">消息类型</param>
        /// <param name="message">消息内容</param>
        /// <param name="className">类名</param>
        private void Write(string mesType, string message, string className)
        {
            lock (writerLock)
            {
                StringBuilder stringBuilder = new StringBuilder(mesType);
                stringBuilder.Append("\t");
                stringBuilder.Append(className);
                stringBuilder.Append("\t");
                stringBuilder.Append(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
                stringBuilder.Append("\t");
                stringBuilder.Append(message);
                streamWriter.WriteLine(stringBuilder.ToString());
                stringBuilder.Clear();
                streamWriter.Flush();
            }
        }

        ~FileLogger()
        {
            Dispose(false);
        }
    }

其它类型实现:

    /// <summary>
    /// 事件日志实现类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    internal class EventLogger<T> : LogBase where T : class, new()
    {
        private readonly Object lockObj=new object();
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public void LogError(string message)
        {
            throw new NotImplementedException();
        }

        public void LogInfo(string message)
        {
            lock (lockObj)
            {
                
            }
        }

        public void LogWarning(string message)
        {
            throw new NotImplementedException();
        }
    }
     /// <summary>
    /// 数据库实现类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    internal class DBLogger<T> : LogBase where T : class, new()
    {
        public void Dispose()
        {
            throw new NotImplementedException();
        }

        public void LogError(string message)
        {
            throw new NotImplementedException();
        }

        public void LogInfo(string message)
        {
            throw new NotImplementedException();
        }

        public void LogWarning(string message)
        {
            throw new NotImplementedException();
        }
    }

数据库与事件日志文件没有具体实现,需要的话自行实现。

    /// <summary>
    /// 日志可以输出到目标地点
    /// </summary>
    public enum LogTarget
    {
        /// <summary>
        /// txt文件
        /// </summary>
        FILE,
        /// <summary>
        /// 数据库
        /// </summary>
        DATABASE,
        /// <summary>
        /// 事件日志
        /// </summary>
        EVENTLOG
    }

看日志工厂:

    /// <summary>
    /// 日志工厂
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LogFactory<T> where T : class, new()
    {
        /// <summary>
        /// 工厂方法
        /// 如果是非文件日志,不必传参fileName与path
        /// </summary>
        /// <param name="target">默认文件</param>
        /// <param name="fileName">默认以时间格式命名</param>
        /// <param name="path">默认当前项目路径</param>
        /// <returns></returns>
        public static LogBase InstanceLog(LogTarget target = LogTarget.FILE, string fileName = null, string path = null)
        {
            LogBase logBase = null;

            switch (target)
            {
                case LogTarget.FILE:
                    if (fileName == null)
                        fileName = DateTime.Now.ToString("yyyyMMddHH") + ".txt";
                    if (path == null)
                        path = System.Environment.CurrentDirectory + "\\Log\\"+ DateTime.Now.ToString("yyyyMMdd");
                    logBase = FileLogger<T>.GetInstance(Path.Combine(path, fileName));
                    break;
                case LogTarget.DATABASE:
                    logBase = new DBLogger<T>();
                    break;
                case LogTarget.EVENTLOG:
                    logBase = new EventLogger<T>();
                    break;
            }

            return logBase;
        }
    }

调用

         LogBase log = LogFactory<Program>.InstanceLog();

            for (int i = 0; i < 10000; i++)
            {
                log.LogInfo("ddd");
                log.LogError("sss");
                log.LogWarning("qqq");
            }
            for (int i = 0; i < 10000; i++)
            {
                new Task(() =>
                {
                    log.LogInfo("ddd");
                    log.LogError("sss");
                    log.LogWarning("qqq");
                }).Start();
            }
            int n = 0;
            while (true)
            {
                if (n >= 1000)
                    break;
                new Task(() =>
                {
                    log.LogInfo("ddd");
                    log.LogError("sss");
                    log.LogWarning("qqq");
                }).Start();
                n++;
            }
            log.LogInfo($"ddd");

            log.Dispose();

 log.Dispose();如果就当前函数使用的话就手动调用释放资源,如果全局使用就不需要调用,能手动的尽量手动(比如窗体关闭closed事件调用),不调用的也没事,等待GC调用,不过GC调用不会及时的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值