Как использовать 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 ответ
Если вам нужен полный контроль над сериализацией в 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>
Начиная с.Net Framework 4.5 (и.Net Core 1.0) это возможно с помощью DataContractJsonSerializerSettings
учебный класс:
DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings
{
EmitTypeInformation = EmitTypeInformation.Never
};
var dcs = new DataContractSerializer(typeof(Test), settings);
В EmitTypeInformation
settings сообщает сериализатору не выводить (раздражает?) __type
параметр во время сериализации.
Доступен ряд других полезных настроек. Вот страница документации дляDataContractJsonSerializerSettings
.
Вам нужен ISerializable
Вот? Что было регулярным DataContractSerializer
не дает тебе? Если вы вернетесь к этому, он должен работать нормально.
По сути, благодаря реализации пользовательской сериализации данные больше не основаны на контрактах, поэтому они должны включать эту дополнительную информацию, чтобы гарантировать, что она сможет понять ее позже.
Итак: есть ли причина для реализации ISerializable
в этом случае?