При использовании ISerializable с DataContractSerializer, как я могу остановить сериализатор от вывода информации о типе?

Чтобы получить больше контроля над сериализацией, я преобразовал класс из [DataContract] в [Serializable], реализуя как GetObjectData, так и специальный десериализационный конструктор. Когда я это делаю, XML-излучение теперь имеет информацию о типе, применяемую ко всем элементам. Я не хочу эту лишнюю информацию, и мне интересно, как сообщить сериализатору, чтобы он не выводил ее.

Здесь пример кода, который использует [DataContract]:

[DataContract(Namespace = "")]
class Test 
{
    public Test() { }
    [DataMember]
    public Nullable<int> NullableNumber = 7;
    [DataMember]
    public int Number = 5;

    public static void Go()
    {
        var test = new Test();
        var dcs = new DataContractSerializer(typeof(Test));
        using (var s = new StreamWriter("test.xml"))
        {
            dcs.WriteObject(s.BaseStream, test);
        }
    }        
}

Это выводит следующий XML (не указывать информацию о типе на Nullable Number и Number - это желаемый результат):

<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <NullableNumber>7</NullableNumber>
  <Number>5</Number>
</Test>

Если я модифицирую вышеуказанный код следующим образом (добавив [Serializable],: ISerializable и два метода сериализации):

[Serializable]
class Test : ISerializable
{
    public Test() { }
    public Nullable<int> NullableNumber = 7;
    public int Number = 5;

    public static void Go()
    {
        var test = new Test();
        var dcs = new DataContractSerializer(typeof(Test));
        using (var s = new StreamWriter("test.xml"))
        {
            dcs.WriteObject(s.BaseStream, test);
        }
    }        
    public Test(SerializationInfo info, StreamingContext context)
    {
        NullableNumber = info.GetInt32("NullableNumber");
        Number = info.GetInt32("Number");
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("NullableNumber", NullableNumber);
        info.AddValue("Number", Number);
    }
}

Теперь он испускает следующий XML. Обратите внимание на информацию типа (i: type = "x: int" ), добавленную к каждому элементу.

<Test xmlns="http://schemas.datacontract.org/2004/07/XMLSerialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
  <NullableNumber i:type="x:int" xmlns="">7</NullableNumber>
  <Number i:type="x:int" xmlns="">5</Number>
</Test>

Почему он это делает? Как я могу остановить его от этого?

Спасибо!

Ответ 1

Вам нужен ISerializable здесь? Каким был обычный DataContractSerializer, который не дал вам? Если вы вернетесь к этому, он должен работать нормально.

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

Итак: есть ли причина для реализации ISerializable в этом случае?

Ответ 2

Если вы хотите полностью контролировать сериализацию в xml, вы можете использовать XmlSerializer

public class Test
{
    [XmlIgnore]
    public Nullable<int> NullableNumber = 7;

    [XmlElement("NullableNumber")]
    public int NullableNumberValue
    {
        get { return NullableNumber.Value; }
        set { NullableNumber = value; }
    }

    public bool ShouldSerializeNullableNumberValue()
    {
        return NullableNumber.HasValue;
    }

    [XmlElement]
    public int Number = 5;
}

пример кода сериализации:

static void Main(string[] args)
{
    XmlSerializer serializer = new XmlSerializer(typeof(Test));
    serializer.Serialize(Console.Out, new Test());
}

результаты:

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Number>5</Number>
  <NullableNumber>7</NullableNumber>
</Test>