c# - 如何从配置文件重构高度重复的阅读部分

标签 c# templates configuration refactoring

我需要将配置文件的多个部分转换为字典。这些词典的值具有不同的类型。以下两个类可以工作,但几乎完全相同:

public class IntConfigSection
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(IntConfigSection));
    public static Dictionary<String, int> LoadSection(string sectionName)
    {
        var ret = new Dictionary<String, int>();
        try
        {
            var offsetsHash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in offsetsHash)
            {
                ret.Add((String)entry.Key, int.Parse((String)entry.Value));
            }
        }
        catch(Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}

public class StringConfigSection
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(StringConfigSection));
    public static Dictionary<String, String> LoadSection(string sectionName)
    {
        var ret = new Dictionary<String, String>();
        try
        {
            var offsetsHash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in offsetsHash)
            {
                ret.Add((String)entry.Key, (String)entry.Value);
            }
        }
        catch (Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}


以下代码无法按要求工作,但它演示了我要完成的工作:

public class ConfigSection<T>
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(StringConfigSection));
    public static Dictionary<String, T> LoadSection(string sectionName)
    {
        var ret = new Dictionary<String, T>();
        try
        {
            var offsetsHash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in offsetsHash)
            {
                //builds but does not always do what I want
                ret.Add((String)entry.Key, (T)entry.Value);
                // does not compile
                //ret.Add((String)entry.Key, T.Parse((String)entry.Value));
            }
        }
        catch (Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}


编辑:我的最终版本如下所示:

public class ConfigSectionLoader
{
    public static Dictionary<String, int> LoadIntSection(string sectionName)
    {
        return ConfigSection<int>.LoadSection(sectionName, int.Parse);
    }

    public static Dictionary<String, String> LoadStringSection(string sectionName)
    {
        return ConfigSection<String>.LoadSection(sectionName, val => val);
    }
}

internal class ConfigSection<T>
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(StringConfigSection));
    internal static Dictionary<String, T> LoadSection(string sectionName, Func<String, T> parseFunc)
    {
        var ret = new Dictionary<String, T>();
        try
        {
            var hash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in hash)
            {
                ret.Add((String)entry.Key, parseFunc((String)entry.Value));
            }
        }
        catch (Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}


我唯一关心的是:val => val是什么都不做的最简单的lambda吗?

最佳答案

您可以传入一个实际上针对该类型进行解析的函数:(注意:未经测试的代码,请考虑一下这是一个主意,而不是有效的代码:D)

public class ConfigSection<T>
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(StringConfigSection));
    public static Dictionary<String, T> LoadSection(string sectionName, Func<String,T> parseFunc)
    {
        var ret = new Dictionary<String, T>();
        try
        {
            var offsetsHash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in offsetsHash)
            {
                ret.Add((String)entry.Key, parseFunc((String)entry.Value));
            }
        }
        catch (Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}


然后将您的实际解析器作为lambda传递(或类似名称。)

或者您实际上可以将解析器包含在该类的构造函数中,然后使其成为成员,因此您不必每次都传递它。

public class ConfigSection<T>
{
    private Func<String, T> myParseFunc = null;

    public ConfigSection<T>(Func<String,T> parParseFunc)
    {
       myParseFunc = parParseFunc;
    }

    private static readonly ILog Log = LogManager.GetLogger(typeof(StringConfigSection));
    public static Dictionary<String, T> LoadSection(string sectionName)
    {
        var ret = new Dictionary<String, T>();
        try
        {
            var offsetsHash = (Hashtable)ConfigurationManager.GetSection(sectionName);
            foreach (DictionaryEntry entry in offsetsHash)
            {
                ret.Add((String)entry.Key, myParseFunc((String)entry.Value));
            }
        }
        catch (Exception e)
        {
            Log.ErrorFormat("LoadSection:" + e);
        }
        return ret;
    }
}


您可以这样称呼它:

ConfigSection<int> = new ConfigSection<int>(int.Parse);

关于c# - 如何从配置文件重构高度重复的阅读部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6671266/

相关文章:

c# - C# (Apache.NMS) 中的 ActiveMQ PooledConnectionFactory

c# - 如何以编程方式增加版本号?

c# - 照片的唯一命名 - GUID 与序列号

c++ - 在将定义参数化类型的某些成员函数的隐式假设下使用模板是错误的吗?

java - 使用 AJAX 的 tomcat 超时配置

configuration - 如何更改 OpenTelemetry Collector 中 Prometheus 导出器的默认路径?

c# - 最近查看的 Cookie

c++ - 如何将 std::vector 设置为模板的默认参数?

c++ - 方法已经定义(模板类)

c# - ASP.NET Core Web API json 配置未复制到调试文件夹