1

我已经设法从几个类轻松生成 XML 文件,如下所示;

public class AllConfig : XMLEncapsulator
{
    [XmlElement("Database-Settings")]
    public DataBaseConfiguration databaseConfiguration { get; set; }
    [XmlElement("Merlin-Settings")]
    public MerlinConfiguration merlinConfiguration { get; set; }
}



public class DataBaseConfiguration : XMLEncapsulator
{
    public string dbIP { get; set; }
    public int ?port { get; set; }
    public string username { get; set; }
    public string password { get; set; }
}

public class MerlinConfiguration : XMLEncapsulator
{
    public string MerlinIP { get; set; }
    public int ?MerlinPort { get; set; }
    public int ?RecievingPort { get; set; }
}


// load classes with information, then;

  try
        {
            allConfig.databaseConfiguration = dbConfig;
            allConfig.merlinConfiguration = merlinConfig;
            allConfig.Save();
        }
        catch (Exception ErrorFinalisingSave)
        {
            MessageBox.Show(ErrorFinalisingSave.Message + "3");
        }

这完美地工作并给了我:

<AllConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <databaseConfiguration>
 <dbIP></dbIP>
 <port></port>
 <username></username>
 <password></password>
</databaseConfiguration>
<merlinConfiguration>
 <MerlinIP></MerlinIP>
 <MerlinPort></MerlinPort>
 <RecievingPort></RecievingPort>
 </merlinConfiguration>
</AllConfig>

但是,我该如何将其重新检索到我的表单中?所以我有这样的东西,但我似乎无法让它工作;

  AllConfig allConfig;
    DataBaseConfiguration dbConfig;
    MerlinConfiguration merlinConfig;

  //need to load here.

//check if values loaded are null, and then load them if they exist into textboxes and such.

我应该加载两个配置类,然后将它们分配给整个配置类吗?还是我需要加载整个类并为此分配子配置类,就像这样;

 allConfig = new AllConfig();

                dbConfig = new DataBaseConfiguration();
                merlinConfig = new MerlinConfiguration();

                allConfig.databaseConfiguration = dbConfig;
                allConfig.merlinConfiguration = merlinConfig;

                allConfig.databaseConfiguration.Load();
                allConfig.merlinConfiguration.Load();

编辑:这是我的加载方法;

 public virtual void Load()
{
    if (File.Exists(DeviceManager.path))
    {
        StreamReader sr = new StreamReader(DeviceManager.path);
        XmlTextReader xr = new XmlTextReader(sr);
        XmlSerializer xs = new XmlSerializer(this.GetType());
        object c;
        if (xs.CanDeserialize(xr))
        {
            c = xs.Deserialize(xr);
            Type t = this.GetType();
            PropertyInfo[] properties = t.GetProperties();
            foreach (PropertyInfo p in properties)
            {
                p.SetValue(this, p.GetValue(c, null), null);
            }
        }
        xr.Close();
        sr.Close();
    }
}
4

4 回答 4

1

以下是我将如何使用您的数据类型来实现它。正如其他人所说,我会简单地删除XMLEncapsulator您从中派生数据类型的内容。另外,请注意,在生成的 xml 中,XmlElement您指定的属性现在受到尊重。

public void Test()
{
   var dbConfig = new DataBaseConfiguration();
   dbConfig.dbIP = "127.0.0.1";
   dbConfig.port = 12345;
   dbConfig.username = "harlam357";
   dbConfig.password = "password";
   var merlinConfig = new MerlinConfiguration();
   merlinConfig.MerlinIP = "192.168.0.1";
   merlinConfig.MerlinPort = 8080;
   merlinConfig.RecievingPort = 8081;
   var config = new AllConfig { databaseConfiguration = dbConfig, merlinConfiguration = merlinConfig };

   string xml = Serialize(config);
   var config2 = Deserialize<AllConfig>(xml);

   Debug.Assert(config2.databaseConfiguration.dbIP == "127.0.0.1");
   Debug.Assert(config2.databaseConfiguration.port == 12345);
   Debug.Assert(config2.databaseConfiguration.username == "harlam357");
   Debug.Assert(config2.databaseConfiguration.password == "password");
   Debug.Assert(config2.merlinConfiguration.MerlinIP == "192.168.0.1");
   Debug.Assert(config2.merlinConfiguration.MerlinPort == 8080);
   Debug.Assert(config2.merlinConfiguration.RecievingPort == 8081);
}

public static string Serialize<T>(T value) where T : class
{
   if (value == null) return null; // throw or whatever fits your use case

   var xmlSerializer = new XmlSerializer(typeof(T));
   using (var stream = new MemoryStream())
   {
      xmlSerializer.Serialize(stream, value);
      return Encoding.UTF8.GetString(stream.GetBuffer());
   }
}

public static T Deserialize<T>(string xml) where T : class
{
   if (xml == null) return null; // throw or whatever fits your use case

   var xmlSerializer = new XmlSerializer(typeof(T));
   using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
   {
      return (T)xmlSerializer.Deserialize(stream);
   }
}

生成的 XML

<?xml version="1.0"?>
<AllConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Database-Settings>
    <dbIP>127.0.0.1</dbIP>
    <port>12345</port>
    <username>harlam357</username>
    <password>password</password>
  </Database-Settings>
  <Merlin-Settings>
    <MerlinIP>192.168.0.1</MerlinIP>
    <MerlinPort>8080</MerlinPort>
    <RecievingPort>8081</RecievingPort>
  </Merlin-Settings>
</AllConfig>
于 2012-06-28T14:15:36.950 回答
1

您正在保存您的课程allConfig.Save();并尝试加载

allConfig.databaseConfiguration.Load();
allConfig.merlinConfiguration.Load();

看起来你没有XmlSerializer正确使用。所以试试这个:

public class Person
{
  public string Name;
  public int Age;
}

p.Name = "Stacey"; p.Age = 30;

//serialize
XmlSerializer xs = new XmlSerializer (typeof (Person));

using (Stream s = File.Create ("person.xml"))
  xs.Serialize (s, p);

//deserialize
Person p2;
using (Stream s = File.OpenRead ("person.xml"))
  p2 = (Person) xs.Deserialize (s);

Console.WriteLine (p2.Name + " " + p2.Age);   // Stacey 30

简而言之 C#

更新:在这里,我对您的代码采用示例。我删除了 XmlEncapsulator,因为我认为它实现了 Save 和 Load 方法,而这并不是真正需要的。如果你真的需要它,你可以退货。不要认为某些事情可能会改变;所以,这里的代码:

         AllConfig all = new AllConfig();
         all.databaseConfiguration = new DataBaseConfiguration();
         all.databaseConfiguration.dbIP = "123";
         all.databaseConfiguration.password = "asd";
         all.databaseConfiguration.port = 123;
         all.databaseConfiguration.username = "sad";
         all.merlinConfiguration = new MerlinConfiguration();
         all.merlinConfiguration.MerlinIP = "123";
         all.merlinConfiguration.MerlinPort = 123;
         all.merlinConfiguration.RecievingPort = 123;

        //serialize 
        XmlSerializer xs = new XmlSerializer(typeof(AllConfig));
        using (Stream s = File.Create ("config.xml"))
            xs.Serialize (s, all); 
        //deserialize 
        AllConfig all2;  
        using (Stream s = File.OpenRead ("config.xml"))
            all2 = (AllConfig)xs.Deserialize(s);
        Console.WriteLine(all2.ToString());
于 2012-06-28T13:31:24.370 回答
1

这是用于从 Xml 反序列化对象的通用方法。这有帮助吗?

public static T Deserialize<T>(string xml) where T : class, new()
{
    if (string.IsNullOrEmpty(xml))
    {
        throw new ArgumentNullException("xml");
    }

    return (T)Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(xml)));
}

public static T Deserialize<T>(Stream xmlStream) where T : class, new()
{
    if (xmlStream == null)
    {
        throw new ArgumentNullException("xmlStream");
    }

    return (T)xmlSerializer.Deserialize(xmlStream);
}
于 2012-06-28T13:23:13.670 回答
0

解决了我自己的问题。这就是我加载它的方式,最后我最终这样做了;

allConfig = new AllConfig();
                dbConfig = new DataBaseConfiguration();
                merlinConfig = new MerlinConfiguration();
                allConfig.databaseConfiguration = dbConfig;
                allConfig.merlinConfiguration = merlinConfig;
                allConfig.Load();

所以我创建了一个我序列化的类的实例,然后创建了包含关闭的类,并将它们分配给主类。然后我加载了主类(我假设通过序列化程序填充了它包含的类,然后我像这样访问它们;

allConfig.databaseConfiguration.port;
allConfig.databaseConfiguration.username;

等等。感谢您的建议,尽管伙计们,真的帮助了我。

于 2012-06-28T14:09:36.117 回答