zoukankan      html  css  js  c++  java
  • 我想实现一个通用的配置读写类

    一个项目,

    有一些配置,

    不想写死,想用一个配置文件管理,需要读写这个配置文件。

    写完了之后,看着一大堆代码,进入了反思,“我是不是自我矛盾了,说了不想写死,还是写了一个死的配置文件读写类,能不能通用一点呢,能不能搞个单例模式控制一下全局访问点呢,……“

    肯定能,通用的单例实现,我见过,懒得写了,直接网上搜索了一下 :) 。

    通用呢,我也不想太发散,做了如下约定:

    配置文件以json文件存放在App_Data文件夹下(我现在做的是ASP.NET MVC项目,其它项目,后续再适当调整吧,大同小异),

    然后,每个配置文件名,就用配置类的类名。

    基本上整体代码都没什么问题,只有一个问题,让我搞了关天,那就是:

    之前,我把初始化的代码,即对json配置文件反序列化的代码写在配置类实例化后就会执行的地方(比如默认构造函数内,或者是会由默认构造函数调用的其它函数内),会导到JSON反序列化时,发生异常,

    进入一个死循环”实例化,初始化,反序列化,……“。

    后来我把这个初始化的代码单独拿出来,在单例实例化之后调用,而不是具体配置类实例化的地方调用,从而解决了这个问题。

    看着这些文字,有点晕,算了,直接上代码吧。

    //用于实现通用单例和隔离类初始化方法的代码
        /// <summary>
        /// 不支持非公共的无参构造函数的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public abstract class BaseInstance1<T> where T : class, new()
        {
            private readonly static object lockObj = new object();
            private static T instance = null;
            public static T Instance
            {
                get
                {
                    if (instance == null)
                    {
                        lock (lockObj)
                        {
                            if (instance == null)
                            {
                                instance = new T();
                            }
                        }
                    }
                    return instance;
                }
            }
        }
    
        /// <summary>
        /// 支持非公共的无参构造函数的
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class BaseInstance2<T> where T : class, IInitable //new(),new不支持非公共的无参构造函数 
        {
            /*
             * 单线程测试通过!
             * 多线程测试通过!
             * 根据需要在调用的时候才实例化单例类!
            */
            private static T _instance;
            private static readonly object SyncObject = new object();
            public static T Instance
            {
                get
                {
                    if (_instance == null)//没有第一重 singleton == null 的话,每一次有线程进入 GetInstance()时,均会执行锁定操作来实现线程同步,
                    //非常耗费性能 增加第一重singleton ==null 成立时的情况下执行一次锁定以实现线程同步
                    {
                        lock (SyncObject)
                        {
                            if (_instance == null)//Double-Check Locking 双重检查锁定
                            {
                                //_instance = new T();
                                //需要非公共的无参构造函数,不能使用new T() ,new不支持非公共的无参构造函数 
                                _instance = (T)Activator.CreateInstance(typeof(T), true); //第二个参数防止异常:“没有为该对象定义无参数的构造函数。”
                                _instance.Init();
                            }
                        }
                    }
                    return _instance;
                }
            }
            public static void SetInstance(T value)
            {
                _instance = value;
            }
        }
    
        public interface IInitable
        {
            /// <summary>
            /// 带有初始化方法
            /// </summary>
            void Init();
        }
    

      

    //配置基类
        /// <summary>
        /// 基础配置类,定义了配置读取的通用操作。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public abstract class BaseConfig<T> : BaseInstance2<T> where T : class , IInitable //, new()
        {
            private string filepath = null;
            private ILog logger = null;
    
            /// <summary>
            /// 
            /// </summary>
            public BaseConfig()
            {
                filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "App_Data", $"{typeof(T).Name}.json");
            }
    
            /// <summary>
            /// 初始化
            /// </summary>
            public virtual void Init()
            {
                try
                {
                    logger = LoggerConfig.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
                    //read config file
                    if (File.Exists(filepath))
                    {
                        var josnstr = File.ReadAllText(filepath, System.Text.Encoding.UTF8);
                        var cfg = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(josnstr);
                        Clone(cfg);
                    }
                }
                catch (Exception ex)
                {
                    logger.Error("读取SysConfig配置文件时报错", ex);
                }
            }
    
            private void Clone(T config)
            {
                var props = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
                foreach (var p in props)
                {
                    p.SetValue(this, p.GetValue(config));
                }
            }
    
            /// <summary>
            /// 保存修改
            /// </summary>
            public void Save()
            {
                try
                {
                    //if (File.Exists(filepath))
                    {
                        string jsonstr = Newtonsoft.Json.JsonConvert.SerializeObject(this);
                        File.WriteAllText(filepath, jsonstr);
                    }
                }
                catch (Exception ex)
                {
                    logger.Error("保存配置文件时报错", ex);
                }
            }
    
        }
    

      

    /// <summary>
        /// 系统配置
        /// </summary>
        public class SysConfig : BaseConfig<SysConfig>, IInitable
        {
            private SysConfig() { }
            public override void Init()
            {
                base.Init();
            }
    
            /// <summary>
            /// 配置字段1
            /// </summary>
            public int XXXCount { get; set; } = 5;
    
            /// <summary>
            /// 配置字段2
            /// </summary>
            public int YYYCount { get; set; } = 6;
    
        }
    

      

    //测试代码
    public ActionResult ShowSysConfig()
            {
                //var cfg1 = new SysConfig();
                var cfg = SysConfig.Instance;
                var jsonstr = Newtonsoft.Json.JsonConvert.SerializeObject(cfg);
    
                return Content(jsonstr, "application/json");
            }
    
            public ActionResult ChangeSysConfig()
            {
                var cfg = SysConfig.Instance;
                cfg.XXXCount += 1;
                cfg.YYYCount += 1;
                SysConfig.Instance.Save();
    
                return ShowSysConfig();
            }
    

      

  • 相关阅读:
    开源的免费的对比工具
    win10 git bash 配置
    Java SSH 不使用终端也能调用环境变量中的指令
    MySQL WITH ROLLUP
    docker安装postgres
    开源的应用容器引擎
    清除浮动有哪几种方法
    js中的yield
    git的速学了解
    string/stringBuffer/StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/luqingfei/p/14384424.html
Copyright © 2011-2022 走看看