一个简单的配置管理器(SettingManager)

在很多.net开发的项目中,我们几乎都会使用到一些自定义的参数,比如说第三方的配置参数之类的.

他们的特点是:1.系统全局 2,可以做成键值对(Dictionary).

我们可以将这些参数放到Web.config,xml或者数据库表中,当然部分不常变的可以直接写在程序中.

为了方便我通常喜欢将他们统放在一个配置管理器中,然后希望别人使用时, 可以像使用AppSetings中的参数一样

初看起来还是比较容易实现,在ConfiguratonManager中定义一个公开属性AppSettings就好了.

实现如下:

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

namespace ConfigManager
{
    public class ConfigurationContainer
    {
        private static ConfigurationContainer m_Instance = null;

        public static ConfigurationContainer Instance
        {
            get
            {
                if (m_Instance == null)
                    m_Instance = new ConfigurationContainer();
                return m_Instance;
            }
        }

        private ConfigurationContainer()
        {

        }

        private ReadOnlyDictionary<string, string> _configuration;
        private Dictionary<string, string> _mutableConfiguration;

        public ReadOnlyDictionary<string, string> Configuration
        {
            get
            {
                //TODO:check is newest or not in database??
                if (_mutableConfiguration == null)
                    Init();

                _configuration =
                    new ReadOnlyDictionary<string, string>(_mutableConfiguration);
                return _configuration;
            }
        }

        public bool Add(string key, string value)
        {
            bool bRet = false;
            if (!_mutableConfiguration.ContainsKey(key))
            {
                _mutableConfiguration.Add(key, value);
                bRet = true;
            }
            return bRet;
        }

        public bool Update(string key, string value)
        {
            bool bRet = false;
            if (_mutableConfiguration.ContainsKey(key))
            {
                _mutableConfiguration[key] = value;
                bRet = true;
            }
            return bRet;
        }

        public bool Remove(string key)
        {
            bool bRet = false;
            if (_mutableConfiguration.ContainsKey(key))
            {
                _mutableConfiguration.Remove(key);
                bRet = true;
            }
            return bRet;
        }

        //private bool ConfigurationAllowed(string key, string value)
        //{
        //    // Put in your checks and balances
        //    // here and return the appropriate result
        //    return true;
        //}

        private void Init()
        {
            _mutableConfiguration = new Dictionary<string, string>();
            _mutableConfiguration.Add("key", "value");
            _mutableConfiguration.Add("key1", "value1");
            _mutableConfiguration["key2"] = "value2";
        }
    }
}

ConfigurationContainer:

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

namespace ConfigManager
{
    public class ConfigManager
    {
        private static IReadOnlyDictionary<string, string> _AppSettings = null;
        public static IReadOnlyDictionary<string, string> Appettings
        {
            get
            {
                //initial ensurer the newest
                _AppSettings = ConfigurationContainer.Instance.Configuration;
                return _AppSettings;
            }
        }

        //Exception:Violence to  Add
        public static void BeNaughtyWithConfiguration()
        {
            IDictionary<string, string> convertToReadWrite
                = (IDictionary<string, string>)_AppSettings;
            //ConfigElement element = convertToReadWrite["key"];
            //element.Value = "Haa Haa";
            //Console.WriteLine(element.Value);
            //Console.WriteLine(convertToReadWrite["key"]);
            //Console.ReadLine();

            convertToReadWrite.Add("Key12345", "xsds");
        }

        public static bool Add(string key, string value)
        {
            return ConfigurationContainer.Instance.Add(key, value);
        }

        public static bool Update(string key, string value)
        {
            return ConfigurationContainer.Instance.Update(key, value);
        }

        public static bool Remove(string key)
        {
            return ConfigurationContainer.Instance.Remove(key);
        }
    }
}

最底层是一个单例模式,并封装了字典的CRUD操作。

客户端测试一下:

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

namespace ConfigManager
{
    class Program
    {
        static void Main(string[] args)
        {
            var settings = ConfigManager.Appettings;

            foreach(var item in settings)
            {
                Console.WriteLine("key:{0},value:{1}",item.Key,item.Value);
            }

            var t1 = ConfigManager.Appettings["key1"];

            //test add
            ConfigManager.Add("t","test");
            //var t2 = ConfigManager.Appettings;
            //update
            ConfigManager.Update("t","test123");

            //remove
            ConfigManager.Remove("t");

            Console.ReadKey();
        }
    }
}

好像也能运行。

那么,问题来了!测试代码改一改,

//test not item in Dictionary
 var t2 = ConfigManager.Appettings["luckyhu"];

代码崩溃了,老兄!

其实上面的代码能够满足一般的需求,但是对使用着来说,仍然不太方便.所以我和同事进一步优化了上述代码.

现在变得更加简洁了.

public class SettingManager : Dictionary<string, string>
    {
        private static SettingManager _Settings = null;
        public static SettingManager Settings
        {
            get
            {
                if (_Settings == null)
                    _Settings = new SettingManager();
                return _Settings;
            }
        }

        private SettingManager()
        {
            //Init Data
            //DataSoure:truely data here...
            for (int i = 0; i < 10; i++)
            {
                var key = String.Format("key{0}", i);
                var value = String.Format("value{0}", i);
                if (!this.Keys.Contains(key))
                    this.Add(key, value);
            }
        }

        public string this[string key]
        {
            get
            {
                if (!this.ContainsKey(key))
                    return String.Empty;
                return base[key];
            }
            set
            {
                base[key] = value;
            }
        }

        public static bool GetBoolValue(string key)
        {
            bool value = false;
            bool.TryParse(Settings[key], out value);
            return value;
        }

        public static int GetIntValue(string key)
        {
            int value = 0;
            int.TryParse(Settings[key], out value);
            return value;
        }
    }

大家看到代码简洁了不少,有了以下改进:

1.代码变少了

2.可以控制索引的返回结果了

3.更多的利用了Dictionary自身的特性,如CRUD

4.增加了自定义类型转换方法

总之,这些努力都是为了方便别人使用.

好吧,看看客户端测试吧

测试结果是OK的

好了,这样一个通用的配置管理器完成了, 当然有更多的需求,还可以对其进行扩展。欢迎大家不吝赐教 .

祝大家新年快乐,万事如意! 2015,一起任性!

时间: 2024-08-15 21:35:59

一个简单的配置管理器(SettingManager)的相关文章

Java实现的一个简单的下载器

package com.shawearn.download;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.EOFException;import java.io.File;http://www.huiyi8.com/jiaoben/import j

可视化程序设计基础(三)——一个简单的播放器(并不)

本次的作业是制作一个简单的播放器,功能仅限于播放视频和音频,虽说是简单的播放器,但其中还是有很多细节需要注意的. 问题一:布局 本来这个问题不应该是一个问题了,之前老师讲过的Stackpanel和Grid等对于布局一个播放器来说绰绰有余,但上次上课老师提到的NavigationView令我十分感兴趣,这是一个uwp应用程序中随处可见的一种布局,节省了开发者很多的时间. 所以我就着手于建立这个NavigationView了,首先我看了一下XAML Controls Gallery,然而其中关于Na

[SimplePlayer] 实现一个简单的播放器

简单的播放器需要实现一个最基本的功能:播放视频文件. 实现这个功能需要包含以下几个步骤: 从视频文件中提取视频图像 在屏幕上显示视频图像 视频帧的同步,也就是保证视频图像在合适的时间在屏幕上显示 从视频文件中提取音频 向音频设备输出音频 音频同步,也就是保证合适的时间输出合适的音频 多线程处理 音视频同步 本实现是通过ffmpeg来实现音视频的提取,通过sdl2来实现音视频的输出,版本如下: libavutil 56. 19.100 / 56. 19.100 libavcodec 58. 23.

C#——一个简单的文件管理器

最近在紧张的学习C#,说实话对C#之前没有太多的接触过,只知道C#的特性与java很相似,接触了之后才发现C#跟java相比区别不是很多,但它是一门实现程序能力比Java还要好的语言(仅代表个人观点). 有许多新手在学习编程语言的时候,都会在递归上面卡住,理解和应用起来会十分的吃力,所以我就自己尝试用递归写了一个很简单很简单很简单的文件管理程序,说它简单是因为他真的没有什么难度,都是很底层的循环和递归,也就只有130多行代码,只是希望能够帮助大家理解应用递归.如果你一点编程基础木有,那请不要直接

C++写一个简单的解析器(分析C语言)

该方案实现了一个分析C语言的词法分析+解析. 注意: 1.简单语法,部分秕.它可以在本文法的基础上进行扩展,此过程使用自上而下LL(1)语法. 2.自己主动能达到求First 集和 Follow 集. 3.处终结符外(有些硬编码的成分),终结符的文法能够自己定义,也就是说读者能够自己定义文法. 4.为方便理解.C语言的文法描写叙述写成中文. 5.程序将词法分析和语法分析结合起来.词法分析的结果作为语法分析的输入. 6.终于结果在控制台显示的有:词法分析.First集.Follow集.Select

ffmpeg+sdl教程----编写一个简单的播放器4(让程序更模块化)

来源:http://blog.csdn.net/mu399/article/details/5815444 音频和视频之间的同步,再那之前需要先做一些准备工作. 为了让程序更模块化,便于扩展,需要把原来main函数中的各个功能模块代码分离出来放在相应的函数中.该教程和上个教程相比代码量和难度都增加很多,比上个教程使用了更多的线程,一定要理解清楚各个函数和数据结构之间的关联以及线程之间如何协同工作. [c-sharp] view plaincopy // ffmpegExe.cpp: 主项目文件.

ffmpeg+sdl教程----编写一个简单的播放器5(同步视频到音频)

来源:http://blog.csdn.net/mu399/article/details/5816566 个人认为,这这部分教程的新增代码量虽然不是最多的,难度却是最大的,重复看了多次才明白,因为有两个问题的困扰,搞得还不清楚: 1.音频和视频既然都有各自的时间戳,各自按各自的时间戳来播放不就行了,为什么还需要同步呢? 2.如果要把视频同步到音频,怎么同步?或者说以什么标准来同步? 第一个问题的答案可能是,一是音频和视频的开始播放的时间是不一样,二是播放每帧音频或视频时可能必须把解码数据,视频

ffmpeg+sdl教程----编写一个简单的播放器3(为视频加入音频)

来源:http://blog.csdn.net/mu399/article/details/5814901 上个教程实现了视频的简单播放,但那是个哑巴电影,完全没有声音. 这个教程第一次用到了SDL的线程,涉及到了两个线程间的同步协调,有几个地方需要特别留意,SDL_OpenAudio库函数会打开音频设备(0是恢 复,其他的是暂停),SDL_PauseAudio库函数可以暂停或者恢复audio_callback函数的执行,程序中的这行代码 “SDL_PauseAudio(0);”执行后,让aud

第二十四篇-用VideoView制作一个简单的视频播放器

这是一个播放本地视频的播放器,videoUrl1是手机里放置视频的路径 效果图: MainActivity.java package com.example.aimee.videotest; import android.Manifest; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.support.annotation.NonN