在 2 个配置文件之间传输值

Transfer values between 2 config files

我有一个问题,我自己也想不通.. 在我的程序中,我有一个自动更新程序,当我的程序更新时,会创建一个新的(更改的,一些新的密钥)配置文件。我想让我的程序做的是,当它更新以查看配置文件(旧的和新的)并将与新文件中的键匹配的旧设置传输到新文件时。

这是旧文件的示例:

 {
  "Setting1": false,
  "Setting2": 123,
  "Setting3": "test",
  "LocationList": {
    "Country": "NL",
    "Locations": [
      {
        "Latitude": 38.556807486461118,
        "Longitude": -121.2383794784546
      },
      {
        "Latitude": -33.859019,
        "Longitude": 151.213098
      },
      {
        "Latitude": 47.5014969,
        "Longitude": -122.0959568
      },
      {
        "Latitude": 51.5025343,
        "Longitude": -0.2055027
      }
    ]
  }
}

这可以是新文件(也可以不同):

{
  "Setting1": null,
  "Setting2": null,
  "Setting3": "",
  "Setting4": ""
  "LocationList": {
    "Country": "",
    "Locations": [
      {
        "Latitude": null,
        "Longitude": null
      },
      {
        "Latitude": null,
        "Longitude": null
      }
    ]
  }
}

预期结果:

 {
  "Setting1": false,
  "Setting2": 123,
  "Setting3": "test",
  "Setting4": ""
  "LocationList": {
    "Country": "NL",
    "Locations": [
      {
        "Latitude": 38.556807486461118,
        "Longitude": -121.2383794784546
      },
      {
        "Latitude": -33.859019,
        "Longitude": 151.213098
      },
      {
        "Latitude": 47.5014969,
        "Longitude": -122.0959568
      },
      {
        "Latitude": 51.5025343,
        "Longitude": -0.2055027
      }
    ]
  }
}

首先,我查看了在 C# 中创建一个 class 并反序列化它,然后我得出的结论是这是不可能的,因为我不知道配置会是什么样子.

其次,我认为使用动态可以解决问题,但事实并非如此,因为我不知道其中的任何键。并且无法弄清楚如何解决这个问题。

最后,我查看了是否可以使用正则表达式,对我来说,这似乎是不可能的..

任何人都可以告诉我他们将如何做的一些想法吗?我不需要代码,只需朝正确的方向推动即可。

P.S。我不想将两者结合起来,当旧文件中有密钥而新文件中没有密钥时,不需要转移(只有列表会完全从旧文件中转移,当列表是empty/filled在新的)。

I don't need code, just a push in the right direction.

将您的配置存储在常规 App.config 文件中并利用 System.Configuration。根据配置的复杂性,您可以使用现成的 <appSettings> 或构建您自己的配置部分和元素。它仍然比自定义配置更容易和防错。

这件事太复杂了,不能为了使用另一种(文本)格式而开始发明轮子。即使您解决了当前的问题,还会有更多问题已经在 System.Configration...

的某处解决

您可以开始探索配置选项here;无论如何,在您最喜欢的搜索引擎中进行定期搜索就可以解决问题...

如果你真的想在JSON中尝试一些东西,我只能推荐优秀的JSON.Net库来为你解析json。使用 LINQ to JSON 您可以轻松地以递归方式在旧配置文件和新配置文件之间找到匹配的键,然后简单地将值从一个复制到另一个

请参阅 http://www.newtonsoft.com/json/help/html/LINQtoJSON.htm

中的文档和一个小示例

简而言之,您可以在伪代码中这样做。显然这不会是超级性能,因为你会递归地遍历两个文件很多次并且可以优化,但同时除非你的配置文件是巨大的 blob 这不应该对任何类型的现代硬件造成任何问题

//load both config files

//load the first token in original file and walk recursively

 //for each token try to match in the new file and write data if required using the same recursive technique to walk the other file

好吧,在遇到一些麻烦后,我设法修复了它(感谢@Louis)。

我是这样做的:

        private static bool TransferConfig(string baseDir, ISession session)
        {
            //if (!session.LogicSettings.TransferConfigAndAuthOnUpdate)
            //    return false;

            var configDir = Path.Combine(baseDir, "Config");
            if (!Directory.Exists(configDir))
                return false;

            var oldConf = GetJObject(Path.Combine(configDir, "config.json.old"));
            var oldAuth = GetJObject(Path.Combine(configDir, "auth.json.old"));

            GlobalSettings.Load("");

            var newConf = GetJObject(Path.Combine(configDir, "config.json"));
            var newAuth = GetJObject(Path.Combine(configDir, "auth.json"));

            TransferJSON(oldConf, newConf);
            TransferJSON(oldAuth, newAuth);

            File.WriteAllText(Path.Combine(configDir, "config.json"), newConf.ToString());
            File.WriteAllText(Path.Combine(configDir, "auth.json"), newAuth.ToString());

            return true;
        }

        private static JObject GetJObject(string filePath)
        {
            return JObject.Parse(File.ReadAllText(filePath));
        }

        private static bool TransferJSON(JObject oldFile, JObject newFile)
        {
            try
            {
                foreach (var newProperty in newFile.Properties())
                    foreach (var oldProperty in oldFile.Properties())
                        if (newProperty.Name.Equals(oldProperty.Name))
                        {
                            newFile[newProperty.Name] = oldProperty.Value;
                            break;
                        }

                return true;
            }
            catch
            {
                return false;
            }
        }