#c# #serialization
#c# #сериализация
Вопрос:
Я хочу только десериализовать определенный элемент данных, не сериализуя его.
Я понимаю, что могу установить EmitDefaultValue =false и установить значение null.
Но я также не хочу изменять значение элемента данных, есть ли какой-либо другой способ добиться этого?
Сериализатором является DataContractSerializer. 🙂
Спасибо.
Комментарии:
1. Я не понимаю. Как вы можете десериализовать то, что не сериализуется?
2. @sehe Я видел множество сценариев, в которых это желательно; это не редкость
3. @MarcGravell: О, ну, я полагаю, вы имеете в виду, что данные могут поступать из какого-то другого источника . Я мог видеть, что это происходит с сериализацией XML. Однако это не очевидно (в общем, вы не можете десериализовать то, что не сериализуется)
Ответ №1:
Вы можете изменить значение элемента данных перед сериализацией (на значение по умолчанию, чтобы оно не сериализовалось), но затем после сериализации вы измените его обратно — используя обратные вызовы [OnSerializing]
и [OnSerialized]
(более подробная информация в этом сообщении в блоге). Это работает нормально, если у вас нет нескольких потоков, сериализующих объект одновременно.
public class StackOverflow_8010677
{
[DataContract(Name = "Person", Namespace = "")]
public class Person
{
[DataMember]
public string Name;
[DataMember(EmitDefaultValue = false)]
public int Age;
private int ageSaved;
[OnSerializing]
void OnSerializing(StreamingContext context)
{
this.ageSaved = this.Age;
this.Age = default(int); // will not be serialized
}
[OnSerialized]
void OnSerialized(StreamingContext context)
{
this.Age = this.ageSaved;
}
public override string ToString()
{
return string.Format("Person[Name={0},Age={1}]", this.Name, this.Age);
}
}
public static void Test()
{
Person p1 = new Person { Name = "Jane Roe", Age = 23 };
MemoryStream ms = new MemoryStream();
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
Console.WriteLine("Serializing: {0}", p1);
dcs.WriteObject(ms, p1);
Console.WriteLine(" ==> {0}", Encoding.UTF8.GetString(ms.ToArray()));
Console.WriteLine(" ==> After serialization: {0}", p1);
Console.WriteLine();
Console.WriteLine("Deserializing a XML which contains the Age member");
const string XML = "<Person><Age>33</Age><Name>John Doe</Name></Person>";
Person p2 = (Person)dcs.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(XML)));
Console.WriteLine(" ==> {0}", p2);
}
}
Комментарии:
1. Действительно помогло. Спасибо!
Ответ №2:
Какой сериализатор?Если это XmlSerializer
, то либо:
public int Foo {get;set;}
[XmlIgnore]
public bool FooSpecified {
get { return false; } // never serialize
set { }
}
или
public int Foo {get;set;}
public bool ShouldSerializeFoo() { return false; }
сделает это. Однако быстрый тест показывает, что это не работает для DataContractSerializer
. protobuf-net также поддерживает оба из них, для информации.
Комментарии:
1. Марк, не мог бы ты связать какую-нибудь документацию по этому вопросу или она недокументирована? Не сомневаюсь, просто любопытно.
2. @Rosie я был уверен, что DCS поддерживает что-то подобное. Я посмотрю еще раз позже.
Ответ №3:
Вы пробовали украшать свойство с помощью [IgnoreDataMember]
?
Комментарии:
1. Тогда он также не будет десериализован
2. спасибо, Марк, это верно, он также не десериализует его: (
Ответ №4:
Существует атрибут System.Xml.Serialization .XmlIgnoreAttribute, который указывает xmkserializers игнорировать ваше свойство. Но это только изменяет поведение сериализации xml.
Комментарии:
1. спасибо, извините, я не уточнил, это не Xml-сериализатор, это DataContractSerializer.
Ответ №5:
добавьте IgnoreDataMemberAttribute
Комментарии:
1. спасибо, но, похоже, он игнорирует элемент данных в целом, т. Е. Он также не будет десериализовать его.