使用單例模式,Dispatcher,實現Log輸出

需求:程序啓動後到關閉,只新建一個Log文件,所有的Log內容都在一個文件中。
注意:爲了避免Log內容錯亂,使用Dispatcher調度

Log
Log.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Log
{

    public delegate string BuildMessage();

    public class Log
    {
        private static string DLL_PATH = "DebugLog.dll";

        private static string OUTPUT_PATH = "";

        private static ILog _iLog = null;

        private static bool _isNeedLog = false;
        static Log()
        {
            try
            {
                if (InitConfigSettings())
                {
                    var type = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + DLL_PATH).GetTypes()?.Single((T) => T.GetInterface(nameof(ILog)) != null);
                    object[] parameters = new object[] { OUTPUT_PATH };
                    _iLog = (ILog)Activator.CreateInstance(type, parameters);
                }
            }
            catch
            {

            }
        }

        public static void Write(string message)
        {
            if (_iLog != null)
            {
                try
                {
                    if(FilterLog())
                    {
                        _iLog.Write(message);
                    }
                }
                catch(Exception ex)
                {
                    _iLog.Write(ex.StackTrace.ToString());
                }
            }
        }

        public static void Wirte(BuildMessage messageAction)
        {
            if (_iLog != null)
            {
                try
                {
                    if (FilterLog())
                    {
                        _iLog.Write(messageAction);
                    }
                }
                catch (Exception ex)
                {
                    _iLog.Write(ex.StackTrace.ToString());
                }
            }
        }

        private static bool InitConfigSettings()
        {
            // get app config file
            string dllPath = string.Format("{0}{1}", AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory, DLL_PATH);
            var appconfig = ConfigurationManager.OpenExeConfiguration(dllPath);
            OUTPUT_PATH = appconfig.AppSettings.Settings["OutPutPath"].Value;
            var _isNeedLog = appconfig.AppSettings.Settings["LogIsNeed"].Value;
            if (_isNeedLog == null || !_isNeedLog.Equals(Boolean.TrueString, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            return true;
        }

        private static bool FilterLog()
        {
            return _isNeedLog == false ? true : false;

        }
    }
}

ILog.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Log
{
    public interface ILog
    {
        void Write(string meaasge);
        void Write(BuildMessage messageAction);
        void Dispose();
    }
}

DebugLog
App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
  </startup>
  <appSettings>
    <add key="LogIsNeed" value="true"/>
    <add key="OutPutPath" value=""/>
  </appSettings>
</configuration>

DebugLogWrite .cs

using Log;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace DebugLog
{
    public class DebugLogWrite : ILog, IDisposable
    {

        private string _outPutPath;

        private bool _isDispose;

        private object _locker = new object();

        private FileStream _fileStream = null;

        private StreamWriter _streamWriter = null;

        private Thread _workingThread = null;

        private Dispatcher _workingDispatcher = null;

        private ManualResetEvent _dispatcherReadSingle = new ManualResetEvent(false);

        private DispatcherOperation _dispatcherOperation = null;

        private string FILE_NAME = "log";
        public DebugLogWrite(string outPutPath)
        {
            try
            {
                var fullPath = Path.GetFullPath(outPutPath);
                if (!Directory.Exists(fullPath))
                {
                    Directory.CreateDirectory(fullPath);
                    var searchPattern = string.Format("log", DateTime.Today.ToString("yyyyMMdd"));
                    var fileList = Directory.GetFiles(fullPath, searchPattern, SearchOption.TopDirectoryOnly)
                        .Where(p => CheckIsNumber(p)).OrderBy(p => new FileInfo(p).Name);
                    var fileNumber = "000";
                    if (fileList.Count() > 0)
                    {
                        FileInfo maxFileInfo = new FileInfo(fileList.Last());
                        fileNumber = maxFileInfo.Name.Substring(4, 3);
                        if (fileNumber != "999")
                        {
                            fileNumber = (Convert.ToInt32(fileNumber) + 1).ToString().PadLeft(3, '0');
                        }

                    }
                    var fileName = string.Format(FILE_NAME, DateTime.Today.ToString("yyyyMMdd"), fileNumber);
                    _outPutPath = Path.Combine(fullPath, fileName);

                    _fileStream = new FileStream(_outPutPath, FileMode.Create, FileAccess.Write);
                    _streamWriter = new StreamWriter(_fileStream, Encoding.UTF8);

                    _workingThread = new Thread(() =>
                    {
                        _workingDispatcher = Dispatcher.CurrentDispatcher;
                        _dispatcherReadSingle.Set();
                        Dispatcher.Run();
                    });
                    _workingThread.Start();
                    _dispatcherReadSingle.WaitOne();
                }
            }
            catch
            {

            }
        }

        public void Dispose()
        {
            if (!_isDispose)
            {
                _isDispose = true;
                Dispose(true);
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    var task = _dispatcherOperation.Task.ContinueWith((p) =>
                    {
                        _dispatcherReadSingle?.Dispose();
                        _dispatcherOperation?.Abort();
                        _workingDispatcher?.InvokeShutdown();
                    });
                }
            }
            catch
            {
                _dispatcherReadSingle?.Dispose();
                _dispatcherOperation?.Abort();
                _workingDispatcher?.InvokeShutdown();
                _streamWriter?.Close();
                _fileStream?.Close();
            }
        }

        public void Write(string meaasge)
        {
            if (!_isDispose)
            {
                var threadId = Thread.CurrentThread.ManagedThreadId;
                lock (_locker)
                {
                    _dispatcherOperation = _workingDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate ()
                    {
                        try
                        {
                            var log = new StringBuilder();
                            log.AppendLine();
                            log.Append(DateTime.Now).Append(meaasge);
                        }
                        catch
                        {
                            _streamWriter?.Close();
                            _fileStream?.Close();
                        }
                    }));
                }
            }
        }

        public void Write(BuildMessage messageAction)
        {
            if (!_isDispose)
            {
                Write(messageAction?.Invoke());
            }
        }

        private bool CheckIsNumber(string file)
        {
            try
            {
                var number = new FileInfo(file).Name.Substring(4, 3);
                int result = 0;
                if (int.TryParse(number, out result))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章