How to serialize a combo box object internally in C # using XElement?

I have an object with members of different types like this:

public class MyObject
{
    public string Str1 = string.Empty;
    public MyEnums.Enum1 E1 = MyEnums.Enum1.Unknown;
    public bool Done = false;
};

      

I have Dictionary

these objects:

Dictionary<string, MyObject> MyObjectsDic = new Dictionary<string, MyObject>();

      

And the serializer for it is like this:

public static void ToXml(string file, string collectionName, Dictionary<string, object> collection)
{
    XElement root = new XElement(collectionName);

    root.Add(collection.Select(x => new XElement("Item", new XAttribute("Object", x.Key),
            x.Value.GetType().GetFields().Select(f => new XElement(f.Name, f.GetValue(x.Value))))));

    root.Save(file);
}

      

The serializer uses abstract Dictionary

as an argument and I need to convert MyObjectsDic

manually. Maybe I am wrong here.

ToXml("MyFile.xml", "MyObjects", MyObjectsDic.ToDictionary(p => p.Key, p => (object)p.Value));

      

I used this tip to make a serializer. This works well, but I need to add a new member to MyObject

List<MyEnums.Enum2> Codes = new List<MyEnums.Enum2>();

      

And store some values ​​here

var a = new MyObject {...};
a.Codes.Add(MyEnums.Enum2.Code1);
a.Codes.Add(MyEnums.Enum2.Code2);
MyObjectsDic.Add("Obj1", a);

      

But this list is serialized to a file like

<Codes>Code1Code2<Codes/>

      

No space or separator. And I don't know how to make it more readable without changes to the serializer and without adding new odd code. The only idea I got is to store the already prepared string in MyObject instead of List <...>. It's not elegant, but simple and works. I do not read this data, I just write and save it as a log to a file.
Or do I need to change my such cool serializer?

Upd.

I used the solution below, but I am getting an exception on Windows XP. It works well on other OSes. I changed the code to be a helper and not an extension of the class.

Exception during dumping MyObjectsDic: There was an error reflecting type 'MyObject'.  
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
at MyXmlSerializerHelper.SerializeToXElement[T](T obj, XmlSerializer serializer, Boolean omitStandardNamespaces) in MyXmlSerializerHelper.cs:line 16
at MyXmlSerializerHelper.  <SerializeToFile>b__0[T](KeyValuePair'2 x) in MyXmlSerializerHelper.cs:line 5

      

The only idea I have is different framework versions or some other religious issues in XP ... Unfortunately, I cannot install any other software or .Net version into production.

+4


source to share


1 answer


Instead of trying to use reflection to manually serialize your class MyObject

, you can use the following methods XmlSerializer

to serialize the dictionary values ​​directly to XElement

, then specify the result in the element tree you are building:

public static class XObjectExtensions
{
    public static XElement SerializeToXElement<T>(this IDictionary<string, T> collection, string collectionName)
    {
        return new XElement(collectionName, collection.Select(x => new XElement("Item", new XAttribute("Object", x.Key), x.Value.SerializeToXElement().Elements())));
    }

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = true)
    {
        var doc = new XDocument();
        using (var writer = doc.CreateWriter())
        {
            XmlSerializerNamespaces ns = null;
            if (omitStandardNamespaces)
                (ns = new XmlSerializerNamespaces()).Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
            (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj, ns);
        }
        var element = doc.Root;
        if (element != null)
            element.Remove();
        return element;
    }
}

      



This automatically results in correct serialization of all fields and properties MyObject

. Using this, the resulting XML looks like this:

<MyObjects>
  <Item Object="Obj1">
    <Str1>Test object</Str1>
    <E1>Unknown</E1>
    <Done>false</Done>
    <Codes>
      <Enum2>Code1</Enum2>
      <Enum2>Code2</Enum2>
    </Codes>
  </Item>
</MyObjects>

      

+3


source







All Articles