как сериализовать список CustomClass с атрибутом объекта

Я хочу сериализовать CMainClass:

[XmlType("Param")]
public class CParam
{
    [XmlElement]
    public string Name;
    [XmlElement]
    public object Value;

    public CParam() { }
    public CParam(string name, object value)
    {
        Name = name;
        Value = value;
    }
}

public class CMainClass
{
    public List<CParam> Parameters = new List<CParam>();
    public CMainClass() { }
    public string GetXML()
    {
        XmlDocument doc = new XmlDocument();
        Type[] extraTypes = new Type[1];
        extraTypes[0] = typeof(CParam);
        XmlSerializer serializer = new XmlSerializer(typeof(CMainClass), extraTypes); 
        MemoryStream stream = new MemoryStream();
        try
        {
            serializer.Serialize(stream, this);
            stream.Position = 0;
            doc.Load(stream);
            return doc.InnerXml;
        }
        catch { throw; }
        finally
        {
            stream.Close();
            stream.Dispose();
        }
    }
}

Тип значения атрибута может быть различным, поэтому используется объектный тип.

вот тестовый код

        CMainClass mc = new CMainClass();
        mc.Parameters.Add(new CParam("number", 123));
        mc.Parameters.Add(new CParam("text", "lorem ipsum"));
        mc.Parameters.Add(new CParam("price", 23.50));

        string s = mc.GetXML();
        Console.WriteLine(s);
        Console.ReadLine();

Все, что я хочу, это получить вывод в следующей форме

<?xml version="1.0"?>
<CMainClass>
    <Parameters>
        <Param Name="number" Value="123" />
        <Param Name="text" Value="lorem ipsum" />
        <Param Name="price" Value="23.5" />
    </Parameters>
</CMainClass>

вместо

<?xml version="1.0"?>
<CMainClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Parameters>
        <Param>
            <Name>number</Name>
            <Value xsi:type="xsd:int">123</Value>
        </Param>
        <Param>
            <Name>text</Name>
            <Value xsi:type="xsd:string">lorem ipsum</Value>
        </Param>
        <Param>
            <Name>price</Name>
            <Value xsi:type="xsd:double">23.5</Value>
        </Param>
    </Parameters>
</CMainClass>

Является ли это возможным? Изменение свойства Value с [XmlElement] на [XmlAttribute] приводит к ошибке.


person Pavel    schedule 24.08.2016    source источник
comment
Известно ли вам об утечке памяти при использовании этого конструктора? blog.forse.no/xmlserializer-cause-memory-leaks   -  person Myrtle    schedule 24.08.2016


Ответы (2)


Если вы хотите использовать атрибуты, вам придется явно указать их типы. Причина ошибки, которую вы получаете при попытке сделать это, заключается в том, что сериализатор не знает, какой на самом деле тип object при десериализации, поскольку, в отличие от элементов, он не может использовать атрибуты типа для указания этого. Вместо этого вам придется изменить его на string и выполнить преобразование самостоятельно.

public class Param
{     
    [XmlAttribute]
    public string Name { get; set; }
    [XmlAttribute]
    public string Value { get; set; }
}

Также обратите внимание, что ваш метод GetXML можно упростить до следующего:

var serializer = new XmlSerializer(typeof(CMainClass));

using (var writer = new StringWriter())
{
    serializer.Serialize(writer, this);
    return writer.ToString();
}  

См. эту скрипту для рабочей демонстрации.

person Charles Mager    schedule 24.08.2016

Чтобы сериализовать класс, вы должны добавить атрибут [Serializable()].

person Himanshu Das    schedule 24.08.2016
comment
Это и не отвечает на вопрос, и фактически неверно - Serializable не имеет ничего общего с XmlSerializer. - person Charles Mager; 24.08.2016