0

How to deserialize element from the list in XAML document using C#?

I use list Settings to save objects of types SettingClassA and SettingClassB. Both classes have a base class SettingClass.

namespace XMLTest
{
    [Serializable]
    public class FHConfig
    {
        public string Name { get; set; } = "Configuration";
        List<SettingClass> settings = null;
        public List<SettingClass> Settings { get { return settings; } set { settings = value; } }
        public FHConfig() {
            settings = new List<SettingClass>();
            settings.Add(new SettingClassA());
            settings.Add(new SettingClassB());
        }
    }
    [Serializable]
    public class SettingClass
    {
        public string SettingName { get; set; } = "Setting 1";
        public SettingClass(){}
    }
    [Serializable]
    public class SettingClassA : SettingClass
    {
        public string SettingName { get; set; } = "Setting A";
        public SettingClassA() { }
    }
    [Serializable]
    public class SettingClassB : SettingClass
    {
        public string SettingName { get; set; } = "Setting B";
        public SettingClassB() { }
    }
}

Serialized xaml file is:

    <FHConfig
      Name="Configuration" xmlns="clr-namespace:XMLTest;assembly=XMLTest" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <FHConfig.Settings>
        <scg:List
          x:TypeArguments="SettingClass"
          Capacity="4">
          <SettingClassA
            SettingName="Setting A" />
          <SettingClassB
            SettingName="Setting B" />
        </scg:List>
      </FHConfig.Settings>
    </FHConfig>

Suppose that I want to deserialize object of class SettingClassA selecting it by tag in xaml file. This problem has been resolved for xml documents in this question How to deserialize only part of an XML document in C#. But using this approach in xaml I can only deserialize the whole FHConfig.Settings list using this code:

    var path = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), file_name);
    var xconfig = XDocument.Load(path);
    List<string> xml_path = new List<string>();
    xml_path.Add("FHConfig.Settings");
    // xml_path.Add("SettingClassA"); // When I want to deserialize only one element of the list, indicating its class name it fails.
    xconfig.CreateReader();
    try
    {
        using (var xmlReader = xconfig.CreateReader())
        {
            if (xml_path != null)
            {
                string tag = "";
                for (int i = 0; i < xml_path.Count(); i++)
                {
                    tag = xml_path[i];
                    xmlReader.ReadToDescendant(tag);
                }
                var obj = XamlServices.Load(xmlReader);
            }
        }
    }
    catch (Exception excep)
    {
        string s_obj = "";
        foreach (var s in xml_path)
            s_obj += " " + s;
        MessageBox.Show("Creating object: " + s_obj + " from xaml: " + excep.Message);
    }

When I try to deserialize one of the list elements, indicating its class name, it returns the next element of the list.

For example, when I try to extract the first occurrence of type SettingClassA, the object created is of class SettingClassB.

How do I deserialize particular element in the list contained in xaml document, knowing its class name?

Alexander Borochkin
  • 4,249
  • 7
  • 38
  • 53
  • I don't understand your question. Why not serialize and deserialize `FHConfig` in the normal way? What does any of this have to do with XAML? I don't understand what you mean by "selecting it by tag in xaml file"; can you show code for that part? – 15ee8f99-57ff-4f92-890c-b56153 Oct 22 '17 at 16:01
  • 1
    I suspect you mean _XML_ and not _"XAML"_. That sample isn't XAML –  Oct 22 '17 at 16:41
  • I read xaml document to the particular tag using `xmlReader.ReadToDescendant(tag);`. Then I try to create object from this part of document using `XamlServices.Load(xmlReader);`. The real `xaml` file I reading is very long and I use it like database, so it is preferable to read only part of it. My C# class does not contain typical XML attributes, like `[XMLRoot]`, so to save it I used `XamlServices.Save()`. It would be impossible to do using `XmlSerializer`. – Alexander Borochkin Oct 22 '17 at 18:18
  • 1
    Why aren’t you using a real database? If it’s too large for a flat file, it’s too large for a flat file. – 15ee8f99-57ff-4f92-890c-b56153 Oct 23 '17 at 01:03

0 Answers0