Пользовательская XML-сериализация с наследованием - PullRequest
1 голос
/ 02 марта 2011

У меня есть следующая структура класса, которую я хочу сериализовать:

    [XmlRoot("SomeClass")]
public class SomeClass
{
    private BaseClass[] _itemArray;
    public BaseClass[] ItemArray
    {
        get { return _itemArray; }
        set { _itemArray = value; }
    }

    public PPSPStatReportMessage()
        : base()
    {
    }
}

public class SomeOtherClass
{
    private int _property5;
    [XmlAttribute("Property5")]
    public int Property5
    {
        get { return _property5; }
        set { _property5 = value; }
    }

    private string _property6;
    [XmlText()]
    public string Property6
    {
        get { return _property6; }
        set { _property6 = value; }
    }

    public SomeOtherClass()
    {
    }
}

[XmlInclude(typeof(DerivedClass1))]
[XmlInclude(typeof(DerivedClass2))]
[XmlRoot("BaseClass")]
[XmlType("")]
public class BaseClass
{
    private string _property1;
    [XmlAttribute("Property1")]
    public string Property1
    {
        get { return _property1; }
        set { _property1 = value; }
    }

    public SomeClass(string PropertyVal)
    {
        _property1 = PropertyVal;
    }
}

[XmlRoot("BaseClass")]
[XmlTypeAttribute(Namespace = "")]
public class DerivedClass1 : BaseClass
{
    private string _property2;
    [XmlAttribute("Property2")]
    public string Property2
    {
        get { return _property2; }
        set { _property2 = value; }
    }


    private SomeOtherClass _property3;
    [XmlElement("SomeOtherClass")]
    public SomeOtherClass Property3
    {
        get { return _property3; }
        set { _property3 = value; }
    }

    public DerivedClass()
        : base("PropertyVal1")
    {
    }
}

[XmlRoot("BaseClass", Namespace = "")]
[XmlType("")]
public class DerivedClass2 : BaseClass
{
    private Int64 _property4;
    [XmlAttribute("Property4")]
    public Int64 Property4
    {
        get { return _property4; }
        set { _property4 = value; }
    }

    public DerivedClass2()
        : base("PropertyVal2")
    {
    }
}

И этот метод я использую для сериализации SomeClass:

public static string SerializeXML(object Value, System.Type ObjectType)
    {
        XmlSerializer serializer = new XmlSerializer(ObjectType);
        XmlSerializerNamespaces namespaceSerializer = new XmlSerializerNamespaces();
        namespaceSerializer.Add("", "");
        StringWriter ms = new StringWriter();
        serializer.Serialize(ms, Value, namespaceSerializer);
        return ms.ToString();
    }

Этот метод генерирует структуру XML, которая выглядит следующим образом:

<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
  <ItemArray>
    <BaseClass d3p1:type="DerivedClass1" Property1="PropertyVal1" Property2="123" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance">
      <SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
    </BaseClass>
    <BaseClass d3p1:type="DerivedClass2" Property="PropertyVal2" Property4="456" xmlns:d3p1="http://www.w3.org/2001/XMLSchema-instance" />
  </ItemArray>
</SomeClass>

Однако мне нужно опустить атрибуты d3p1: type и xmlns: d3p1 и сгенерировать структуру XML, которая выглядит следующим образом:

<?xml version="1.0" encoding="utf-16"?>
<SomeClass>
  <ItemArray>
    <BaseClass Property1="PropertyVal1" Property2="123">
      <SomeOtherClass Property5="0" >STRING DATA</SomeOtherClass>
    </BaseClass>
    <BaseClass Property="PropertyVal2" Property4="456" />
  </ItemArray>
</SomeClass>

Как вы можете видеть в коде, я пытался использовать XmlType и XmlTypeAttribute, но безуспешно.

Любой совет, как мне сгенерировать структуру XML, как описано выше (без атрибутов d3p1: type и xmlns: d3p1)?

Ответы [ 3 ]

3 голосов
/ 01 августа 2013

Вам нужно, чтобы элементы подкласса назывались "BaseClass" - или имя производного класса подойдет?

Я сериализую аналогичные структуры подклассов, а также хотел избавиться от тегов «d3p1: type» и «xmlns: d3p1» - вместо этого я заменил теги «BaseClass» производными тегами класса. Так что для вашего примера можно сгенерировать xml:

<ItemArray>
    <DerivedClass1 Property1="PropertyVal1" Property2="123">
        ....
    </DerivedClass1>

Вы используете атрибут XmlInclude в BaseClass, чтобы сообщить serliazer, какие производные классы ожидать. Вместо этого вы можете сообщить сериализатору об ожидаемых подтипах для каждого элемента:

public class SomeClass
{
    private BaseClass[] _itemArray;

    [XmlElement(typeof(DerivedClass1))]
    [XmlElement(typeof(DerivedClass2))]
    public BaseClass[] ItemArray
    { 
        get { return _itemArray; }
        set { _itemArray = value; }
}

Устранение атрибутов типа. Десериализация также будет работать нормально.

2 голосов
/ 02 марта 2011

Вы не можете выполнить то, что хотите напрямую.

Если сериализуемый тип не является точным содержащимся типом, .NET должен отследить, какой тип действительно существует, чтобы обеспечить правильную десериализацию.

Чтобы выполнить то, что вы хотите - используйте RegEx.Replace () или другую постобработку для замены пространств имен.

(например, сериализация объекта, который действительно является строкой, вызовет эту проблему).

0 голосов
/ 02 марта 2011
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.Indent = true;

using (XmlWriter writer = XmlWriter.Create(file, settings))
{
    XmlSerializer serializer = new XmlSerializer(source.GetType());

    XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
    namespaces.Add(string.Empty, string.Empty);
    // ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...