Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a readonly field be initialized when using DataContractSerializer?

DataContractSerializer does not call a constructor or invoke field initializers when deserializing:

DataContractSerializer doesn't call my constructor?

Field Initializer in C# Class not Run when Deserializing

Setting the initial value of a property when using DataContractSerializer

Is it possible to initialize a readonly field after object deserialization? Must I abandon that language feature in order to use DataContractSerializer?

like image 834
Eric J. Avatar asked Feb 23 '12 19:02

Eric J.


2 Answers

I'm not sure doing this is a good idea, but you can change the value of a readonly field outside the constructor or field initializer by using reflection.

Putting something like:

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

in your deserialization callback should work.

like image 194
svick Avatar answered Oct 30 '22 07:10

svick


Yes, using DataContractSerializer you can serialize a readonly field. You can even serialize a non-public readonly field.

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;
        }
    }
}
like image 38
Jason Kresowaty Avatar answered Oct 30 '22 07:10

Jason Kresowaty