Как я могу предотвратить сериализацию элемента данных

#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. спасибо, но, похоже, он игнорирует элемент данных в целом, т. Е. Он также не будет десериализовать его.