【问题标题】:Manage complex string array in C#在 C# 中管理复杂的字符串数组
【发布时间】:2015-07-29 06:15:13
【问题描述】:

我想使用存储在web.config 中的字符串数组来轻松更改其值,格式为:full_w=670|small_w=100,q=low|tiny_h=30,c=true。每个模板都由 | 分割。 (管道),然后这些集合中的每一个都包含一个名称(_ 的左侧)及其对应的值(_ 的右侧),这些值可以是多个,并且每个都由 ,(逗号)分隔。我认为这可能符合 3D 数组的条件,我似乎无法以一种明智的方式轻松地阅读它。关于从该字符串中读取/管理数据的最佳方式的任何想法或解决方案?

基本上,最后我希望能够调用模板small 并读取其值,在本例中为width=100quality=low

【问题讨论】:

  • 为方便起见,您可以将其保存到字典(键、值)对中。键为 full、small、tiny,值为 (full: w670), (small: w100, qlow)。只要知道当你对待你的价值时,第一个字母就是标识符

标签: c# arrays web-config


【解决方案1】:

这是我为解析这些设置字符串之一而编写的函数:

public static Dictionary<string, Dictionary<string, string>> getSettings(string settingsStr)
{
    return settingsStr.Split('|').ToDictionary(
        template => template.Split('_')[0],
        template => template.Split('_')[1].Split(',').ToDictionary(
            setting => setting.Split('=')[0],
            setting => setting.Split('=')[1]));
}

它只是使用了很多字符串.Splitting 和.ToDictionarying。

这是测试,表明它有效:

var result = getSettings("full_w=670|small_w=100,q=low|tiny_h=30,c=true");
/*
result = {
    [ "full" => [ "w" => "670" ] ]
    [ "small" => [ "w" => "100", "q" => "low" ] ]
    [ "tiny" => [ "h" => "30", "c" => "true" ] ]
}
*/

要从模板small 中读取值wq,您可以这样做:

int width = int.Parse(result["small"]["w"]);
string quality = result["small"]["q"];

编辑:另外,如果您想将Dictionary&lt;string, Dictionary&lt;string, string&gt;&gt; 转换回单个设置字符串,您可以使用此方法:

public static string getSettingsStr(Dictionary<string, Dictionary<string, string>> settings)
{
    return string.Join("|",
        settings.Select(kvp =>
            kvp.Key + "_" + string.Join(",",
                kvp.Value.Select(setting =>
                    setting.Key + "=" + setting.Value))));
}

用途:

string settingsStr = getSettingsStr(result);
// settingsStr = "full_w=670|small_w=100,q=low|tiny_h=30,c=true"

如果要检查特定模板或设置是否存在,请使用.ContainsKey() 方法:

// If I have "Dictionary<string, Dictionary<string, string>> settings;"
int width = -1;
string quality = null;
if (settings.ContainsKey("small"))
{
    if (settings["small"].ContainsKey("w"))
        width = int.Parse(settings["small"]["w"]);
    if (settings["small"].ContainsKey("q"))
        quality = settings["small"]["q"];
}

【讨论】:

  • 我喜欢,真的很喜欢。它的字典和炒锅很适合我的需要,这是公认的答案。还有一件事;如果字典中不存在键,如何返回 null 或空,例如; result["small"]["a"];?谢谢。
  • @NelsonPires 使用此解决方案,最好简单地检查模板/设置是否存在(使用.ContainsKey(key) 方法)。此外,如果这是答案,请考虑将其标记为这样,以便未来的访问者可以轻松分辨。
  • 找不到.ContainsKey(key),可以举个例子吗?标记为已接受,谢谢。
  • 太好了,完美运行。我想知道,由于我正在阅读 web.config 并且这将在图像处理程序中使用,对于大型画廊的情况,web.config 是否会被击中/读取每个 .net 框架的图像缓存网络.config 值并使用它直到文件被修改?
  • 刚刚找到了我最后一个问题的答案,以防万一有人还需要知道,web.config 不会在每次读取其中的值时都被命中,框架将其保存在内存中直到应用程序重新启动或文件被修改,这也会重新启动应用程序。
【解决方案2】:

您是否考虑过将普通的旧 XML 序列化与您自己的普通旧 C# 对象一起使用。这是一个例子:

public class Program
{
    static void Main(string[] args)
    {
        var data = new MyConfig[2];

        for (int i = 0; i < 2; i++)
        {
            data[i] = new MyConfig { Name = "Name" + i };

            data[i].Properties = new MyConfigAttribute[]
            {
                new MyConfigAttribute { Name = "Property Name " + i, Value = "Property Value " + i },
                new MyConfigAttribute { Name = "2nd Property Name " + i, Value = "2nd Property Value " + i },
            };
        }

        var serializer = new XmlSerializer(typeof(MyConfig[]));
        using (StreamWriter tw = File.CreateText(@"c:\temp\myconfig.xml"))
        {
            serializer.Serialize(tw, data);
        }

        using (StreamReader tw = File.OpenText(@"c:\temp\myconfig.xml"))
        {
            var readBack = serializer.Deserialize(tw);
        }


        Console.ReadLine();
    }

    [XmlRoot("MY_CONFIG")]
    public class MyConfig
    {
        [XmlElement("NAME")]
        public string Name { get; set; }

        [XmlArray]
        [XmlArrayItem(typeof(MyConfigAttribute))]
        public MyConfigAttribute[] Properties { get; set; }
    }

    [XmlRoot("MY_CONFIG_ATTRIBUTE")]
    public class MyConfigAttribute
    {
        [XmlElement("ATTRIBUTE_NAME")]
        public string Name { get; set; }

        [XmlElement("ATTRIBUTE_VALUE")]
        public string Value { get; set; }
    }
}

基本上,您创建一个类来存储您的个人属性(在本例中为 MyConfigAttribute),将其包装在另一个类中为一组相关属性提供您的名称(在本例中为 MyConfig),然后使用普通的 XML 序列化来编写将设置输出到单个 XML 文件,例如这部分代码

        var serializer = new XmlSerializer(typeof(MyConfig[]));
        using (StreamWriter tw = File.CreateText(@"c:\temp\myconfig.xml"))
        {
            serializer.Serialize(tw, data);
        }

您可以使用这部分代码再次将其读回对象:

        using (StreamReader tw = File.OpenText(@"c:\temp\myconfig.xml"))
        {
            var readBack = serializer.Deserialize(tw);
        }

这样做的好处是:

  • 易于理解和使用
  • 您可以向自定义类添加功能,例如将值添加到属性数组,从而使其自身能够在其周围包裹自定义屏幕。

在 Google 上查找 C# XML 序列化!

【讨论】:

  • 谢谢理查德,但我正在阅读 web.config,因此不需要使用另一个 xml 文件,但您的答案可能会在其他事情上派上用场。再次感谢。
  • Nelson,如果你真的需要使用 web 配置文件,那么你应该探索编写自定义部分 link
  • &lt;appSettings&gt; 可以满足我的需求,它可以轻松读/写,但感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2010-11-14
  • 1970-01-01
  • 2015-10-21
相关资源
最近更新 更多