通用消息打印接口

目录

[TOC]

一、通用消息打印接口

1.简介

将消息打印模块封装一层,并对外提供消息打印接口。如此一来通过封装可以为消息打印提供更多自定义空间。

比如:

  • 增加多个消息通道(Channel)每个通道之间互不干扰,可以为不同类型的消息提供不同的消息打印方法;
  • 为整个消息打印模块提供统一的开关,从编译层面控制消息打印,可提升实机运行效率。

通用消息打印模块集成在常用工具中(HTUtility

2.使用方式

步骤:

  • Step1.点击菜单栏:“HTUtility/7.LoggerSwitch” 用于开关消息打印

    picture0

    开启之后,控制台消息会显示:

    picture1

  • Step2.为不同的消息通道(Channel)实现不同的消息监听对象

            public class UnityDebugListener : ILoggerListener
            {
                public void Log(string msg)
                {
                    Debug.Log(msg);
                }
            }
            public class UnityWarningListener : ILoggerListener
            {
                public void Log(string msg)
                {
                    Debug.LogWarning(msg);
                }
            }
            public class UnityErrorListener : ILoggerListener
            {
                public void Log(string msg)
                {
                    Debug.LogError(msg);
                }
            }
    
  • Step3.初始化消息打印模块,并为其注册消息打印监听

    UnityDebugListener unityDebugListener = new UnityDebugListener();
    UnityWarningListener unityWarningListener = new UnityWarningListener();
    UnityErrorListener unityErrorListener = new UnityErrorListener();
    Logger.Instance.Init(true);
    Logger.Instance.AddListener(Logger.Channel.INFO, unityDebugListener);
    Logger.Instance.AddListener(Logger.Channel.TODO, unityDebugListener);
    Logger.Instance.AddListener(Logger.Channel.DEBUG, unityDebugListener);
    Logger.Instance.AddListener(Logger.Channel.WARNING, unityWarningListener);
    Logger.Instance.AddListener(Logger.Channel.ERROR, unityErrorListener);
    
  • Step4.可以使用自定义消息打印了

    Logger.Info("测试 Logger");
    Logger.Todo("测试 Logger");
    Logger.Debug("测试 Logger");
    Logger.Warning("测试 Logger");
    Logger.Error("测试 Logger");
    

3.开关原理

为消息打印自定义了宏编译#define LOGGER_OPEN

当消息打印功能关闭时:

picture2

picture4

当消息打印功能开启时:

picture3

picture5

4.代码

普通类的单例模板:

/****************************************************
	文件:HTSingleton.cs
	作者:HuskyT
	邮箱:1005240602@qq.com
	日期:2020/3/25 14:41:19
	功能:普通单例模板
*****************************************************/

namespace HTUtility
{
    public class HTSingleton<T> where T : class, new()
    {
        private static T mInstance = null;
        public static T Instance
        {
            get
            {
                if (mInstance == null)
                {
                    mInstance = new T();
                }
                return mInstance;
            }
        }
    }
}

HTLogger

/****************************************************
	文件:HTLogger.cs
	作者:HuskyT
	邮箱:1005240602@qq.com
	日期:2020/3/25 14:4:3
	功能:打印消息接口
*****************************************************/
//#define LOGGER_OPEN
using System;

namespace HTUtility
{
    /*
     * 使用方法:
     * 1.新建 Class 实现 ILoggerListener 接口,实现 Log 方法
     * 2.初始化 HTLogger
     * 3.向 HTLogger 中不同的 Channel 分别添加 LoggerListener 监听
     * 4.在菜单栏“HTUtility/6.LoggerSwitch”中开启(切换)Logger 开关
     */
    public interface ILoggerListener
    {
        void Log(string msg);
    }
    public class HTLogger : HTSingleton<HTLogger>
    {
        public enum Channel
        {
            Default = 0,
            //打印信息(程序正常运行的信息)
            Info,
            //待完成的信息
            Todo,
            //debug时输出的信息
            Debug,
            //警告信息
            Warning,
            //错误信息
            Error,
        }
        private static bool mHasInit = false;
        //是否需要包装 消息 (给消息加上 日期 和 Channel)
        private static bool mNeedPackageMsg = false;
        private static bool[] mChannelEnableArray;
        private static ILoggerListener[] mChannelListenerArray;

        /// <summary>
        /// 初始化,默认开启所有频道
        /// </summary>
        public void Init(bool needPackageMsg = true)
        {
            mChannelEnableArray = new bool[Enum.GetValues(typeof(Channel)).Length];
            mChannelListenerArray = new ILoggerListener[Enum.GetValues(typeof(Channel)).Length];
            //默认初始开启所有信息打印通道
            for (int i = 0; i < mChannelEnableArray.Length; i++)
            {
                mChannelEnableArray[i] = true;
            }
            mNeedPackageMsg = needPackageMsg;
            mHasInit = true;
        }
        /// <summary>
        /// 重置
        /// </summary>
        public void Reset()
        {
            if (mHasInit == false) return;
            for (int i = 0; i < mChannelListenerArray.Length; i++)
            {
                RemoveListener((Channel)i);
            }
            mChannelListenerArray = null;
            mChannelEnableArray = null;
            mNeedPackageMsg = false;
            mHasInit = false;
        }
        /// <summary>
        /// 设置频道开关状态
        /// </summary>
        /// <param 频道="channel"></param>
        /// <param 开关状态="state"></param>
        public void SetChannelState(Channel channel, bool state)
        {
            if (mHasInit == false) return;
            mChannelEnableArray[(int)channel] = state;
        }
        public void AddListener(Channel channel, ILoggerListener listener)
        {
            if (mHasInit == false) return;
            if (mChannelEnableArray[(int)channel] == false) return;
            mChannelListenerArray[(int)channel] = listener;
        }
        public void RemoveListener(Channel channel)
        {
            if (mHasInit == false) return;
            mChannelListenerArray[(int)channel] = null;
        }

        #region 打印消息
        public static void Info(string msg)
        {
#if LOGGER_OPEN
            LogMsg(msg, Channel.Info, mNeedPackageMsg);
#endif
        }
        public static void Todo(string msg)
        {
#if LOGGER_OPEN
            LogMsg(msg, Channel.Todo, mNeedPackageMsg);
#endif
        }
        public static void Debug(string msg)
        {
#if LOGGER_OPEN
            LogMsg(msg, Channel.Debug, mNeedPackageMsg);
#endif
        }
        public static void Warning(string msg)
        {
#if LOGGER_OPEN
            LogMsg(msg, Channel.Warning, mNeedPackageMsg);
#endif
        }
        public static void Error(string msg)
        {
#if LOGGER_OPEN
            LogMsg(msg, Channel.Error, mNeedPackageMsg);
#endif
        }
        public static void LogMsg(string msg, Channel channel, bool needPackageMsg)
        {
            if (mHasInit == false) return;
            if (mChannelEnableArray[(int)channel] == false) return;
            ILoggerListener logger = mChannelListenerArray[(int)channel];
            if (logger == null) return;
            string message = msg;
            if (needPackageMsg)
                message = PackageMsg(msg, channel);
            logger.Log(message);
            Console.WriteLine(message);
        }
        #endregion

        /// <summary>
        /// 包装信息
        /// </summary>
        /// <param 信息="msg"></param>
        /// <param 频道="channel"></param>
        /// <returns></returns>
        private static string PackageMsg(string msg, Channel channel)
        {
            return string.Format("({0})[{1}]:{2}", DateTime.Now.ToString(), channel, msg);
        }
    }
}

LoggerSwitchMenu

/****************************************************
	文件:LoggerSwitchMenu.cs
	作者:HuskyT
	邮箱:1005240602@qq.com
	日期:2020/3/25 15:55:31
	功能:消息打印开关(决定 HTLogger 是否参与编译)
*****************************************************/

using UnityEngine;
using UnityEditor;
using System.IO;

namespace HTUtility
{
    public class LoggerSwitchMenu : MonoBehaviour
    {
        public enum LoggerModeEnum
        {
            //初始未设置时的默认值
            Default = 0,
            //关闭打印消息
            Close = 1,
            //开启打印消息
            Open = 2,
        }
        /// <summary>
        /// 使用 EditorPrefs 存储的 key 值
        /// </summary>
        private const string LOGGER_MODE_KEY = "Logger Mode";
        /// <summary>
        /// 菜单路径
        /// </summary>
        private const string LOGGER_SWITCH_MENU_PATH = "HTUtility/7.LoggerSwitch";
        /// <summary>
        /// HTLogger 脚本路径
        /// </summary>
        private static string mLoggerScriptPath = Application.dataPath + "/HTUtility/7-HTLogger/HTLogger.cs";
        /// <summary>
        /// LoggerMode 在未设置的时候默认值为 0
        /// </summary>
        private static LoggerModeEnum mLoggerMode = LoggerModeEnum.Default;

        /// <summary>
        /// 打印消息模式
        /// (此时可打印消息,若关闭打印消息功能,则不会编译,以优化性能)
        /// </summary>
        private static LoggerModeEnum LoggerMode
        {
            get
            {
                //第一次设置 LoggerMode
                if (mLoggerMode == LoggerModeEnum.Default)
                {
                    //获取存储的 LoggerMode 值,默认为 Close
                    mLoggerMode = (LoggerModeEnum)EditorPrefs.GetInt(LOGGER_MODE_KEY, (int)LoggerModeEnum.Close);
                }
                return mLoggerMode;
            }
            set
            {
                mLoggerMode = value;
                EditorPrefs.SetInt(LOGGER_MODE_KEY, (int)value);
            }
        }

        /// <summary>
        /// 切换 LoggerMode
        /// </summary>
        [MenuItem(LOGGER_SWITCH_MENU_PATH, false, 7)]
        private static void SwitchLoggerMode()
        {
            LoggerMode = LoggerMode == LoggerModeEnum.Open ? LoggerModeEnum.Close : LoggerModeEnum.Open;

            //若为打印消息模式:
            if (LoggerMode == LoggerModeEnum.Open)
            {
                //读取 HTLogger 脚本
                string[] contents = File.ReadAllLines(mLoggerScriptPath);
                for (int i = 0; i < contents.Length; i++)
                {
                    if (contents[i].StartsWith("//#define"))
                    {
                        if (contents[i].Contains("LOGGER_OPEN"))
                        {
                            contents[i] = "#define LOGGER_OPEN";
                            break;
                        }
                    }
                }
                File.WriteAllLines(mLoggerScriptPath, contents);
            }
            //若为关闭打印消息模式:
            else
            {
                //读取 HTLogger 脚本
                string[] contents = File.ReadAllLines(mLoggerScriptPath);
                for (int i = 0; i < contents.Length; i++)
                {
                    if (contents[i].StartsWith("#define"))
                    {
                        if (contents[i].Contains("LOGGER_OPEN"))
                        {
                            contents[i] = "//#define LOGGER_OPEN";
                            break;
                        }
                    }
                }
                File.WriteAllLines(mLoggerScriptPath, contents);
            }
            AssetDatabase.Refresh();
            Debug.Log("自定义消息打印功能:" + LoggerMode);
        }

        /// <summary>
        /// 切换 LoggerSwitch 的验证方法
        /// 每次编译都会执行此方法
        /// </summary>
        [MenuItem(LOGGER_SWITCH_MENU_PATH, true, 7)]
        private static bool SwitchLoggerModeValidate()
        {
            bool openLogger = LoggerMode == LoggerModeEnum.Open ? true : false;
            //将菜单设置成可切换状态
            //参数(菜单,依据什么切换)
            Menu.SetChecked(LOGGER_SWITCH_MENU_PATH, openLogger);
            return true;
        }
    }
}

测试代码

/****************************************************
	文件:UnityLoggerListener.cs
	作者:HuskyT
	邮箱:1005240602@qq.com
	日期:2020/3/25 15:19:55
	功能:例子:展示如何在 Unity 中使用 HTLogger
*****************************************************/

using UnityEngine;

namespace HTUtility.Example
{
    public class UnityLoggerExample : MonoBehaviour
    {
        public class UnityDebugListener : ILoggerListener
        {
            public void Log(string msg)
            {
                Debug.Log(msg);
            }
        }
        public class UnityWarningListener : ILoggerListener
        {
            public void Log(string msg)
            {
                Debug.LogWarning(msg);
            }
        }
        public class UnityErrorListener : ILoggerListener
        {
            public void Log(string msg)
            {
                Debug.LogError(msg);
            }
        }

        private void Start()
        {
            UnityDebugListener unityDebugListener = new UnityDebugListener();
            UnityWarningListener unityWarningListener = new UnityWarningListener();
            UnityErrorListener unityErrorListener = new UnityErrorListener();
            HTLogger.Instance.Init(true);
            HTLogger.Instance.AddListener(HTLogger.Channel.Info, unityDebugListener);
            HTLogger.Instance.AddListener(HTLogger.Channel.Todo, unityDebugListener);
            HTLogger.Instance.AddListener(HTLogger.Channel.Debug, unityDebugListener);
            HTLogger.Instance.AddListener(HTLogger.Channel.Warning, unityWarningListener);
            HTLogger.Instance.AddListener(HTLogger.Channel.Error, unityErrorListener);

            HTLogger.Info("测试 Logger 成功!");
            HTLogger.Todo("测试 Logger 成功!");
            HTLogger.Debug("测试 Logger 成功!");
            HTLogger.Warning("测试 Logger 成功!");
            HTLogger.Error("测试 Logger 成功!");
        }
    }
}

运行结果:

picture6