Um campo readonly pode ser inicializado ao usar o DataContractSerializer?

9

DataContractSerializer não chama um construtor nem invoca inicializadores de campo ao desserializar:

O DataContractSerializer não chama meu construtor?

Campo inicializador na classe C # não executado quando desserializing

Definindo o valor inicial de uma propriedade ao usar DataContractSerializer

É possível inicializar um campo readonly após a desserialização do objeto? Devo abandonar esse recurso de idioma para usar o DataContractSerializer?

    
por Eric J. 23.02.2012 в 20:55
fonte

3 respostas

3

Não sei se isso é uma boa ideia, mas você pode alterar o valor de um campo readonly fora do construtor ou do inicializador de campo usando reflexão.

Colocando algo como:

typeof(MyType).GetField("Field").SetValue(this, value);

no seu retorno de chamada de desserialização deve funcionar.

    
por svick 24.02.2012 / 02:34
fonte
2

Sim, usando DataContractSerializer você pode serializar um campo readonly . Você pode até mesmo serializar um campo que não seja public readonly .

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;

namespace ConsoleApplication30
{
    class Program
    {
        static void Main(string[] args)
        {
            Test a = new Test(1, 2);
            Test b;
            using (var ms = new MemoryStream())
            {
                DataContractSerializer ser = new DataContractSerializer(typeof(Test));
                ser.WriteObject(ms, a);
                ms.Position = 0;
                b = (Test) ser.ReadObject(ms);
            }
            Trace.Assert(a.Data1 == b.Data1);
            Trace.Assert(a.Data2 == b.Data2);
        }
    }

    [DataContract]
    public class Test
    {
        [DataMember]
        public readonly int Data1;

        [DataMember]
        private readonly int _data2;
        public int Data2
        {
            get { return _data2; }   
        }

        public Test(int data1, int data2)
        {
            Data1 = data1;
            _data2 = data2;
        }
    }
}
    
por Jason Kresowaty 24.02.2012 / 02:35
fonte
0

Encontrei um jeito limpo de conseguir o que você está procurando sem quebrar seu design.

Usar esse método garantirá que seu construtor seja chamado e seu campo somente leitura seja definido corretamente.

O que você precisa é realmente serializar e desserializar [DataMember] campos marcados de uma classe DataModel.

Isso evitará que qualquer comportamento não intencional aconteça, sabendo que o DataContractSerializer não chama o construtor ao desserializar.

namespace MyApp.DataModel
{
    //It is not mandatory to specify the DataContract since a default one will be
    //provided on recent version of .Net, however it is a good practice to do so.
    [DataContract(Name = "MyClassDataModel", Namespace = "MyApp.DataModel")]
    public class MyClassDataModel
    {
        [DataMember]
        public bool DataMemberExample{ get; set; }
    }

}

Para desserializar e serializar, agora você pode usar essa classe para manter seus valores.

Após o carregamento, você pode criar um novo objeto de modelo de dados e passá-lo para sua classe que precisa ter seu construtor chamado.

public MyObjectThatNeedToBeConstructed LoadData(){
    // ... 
    // get your reader (Stream) from the file system or wherever it's located
    var deserializer = new DataContractSerializer(typeof(MyClassDataModel));
    var storedModel = (MyClassDataModel)deserializer.ReadObject(reader);

    return new MyObjectThatNeedToBeConstructed(storedModel);
}

Ao salvar, você pode extrair os dados necessários da sua classe que contêm o campo ReadOnly.

public void SaveData(MyObjectThatNeedToBeConstructed myObject){
    // ... 
    // get your writer (Stream) from memory or wherever it's located
    var serializer = new DataContractSerializer(typeof(MyClassDataModel));
    var dataModel = new MyClassDataModel{ DataMemberExample = myObject.DataMember};
    serializer.WriteObject(writer, dataModel);
}

É claro que você terá que adicionar uma sobrecarga ao construtor e talvez tenha que ajustar um pouco o exemplo, mas acho que você entendeu o cenário.

    
por ForceMagic 12.12.2013 / 02:58
fonte