0

My class looks like this:

public class MyClass
{
    private void MyClass() { } //just to satisfy the XML serializer
    public void MyClass(int a, int b)
    {
        A = a;
        B = b;
        C = a + b;
    }
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; private set; } //private set is only to
                                       //satisfy the XML Serializer
    public void DoSomeMath()
    {
        Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
    }
}

This works fine when I instantiate my own myClass object with a & b parameters, but the deserializer will only call the paramaterless constructor. How do I initialize C without creating another method and calling that after I deserialize?

  • There are serialization events for this which serializer are you using each one is different – Jim Jul 14 '16 at 03:57
  • `System.Xml.Serialization.XmlSerializer` – Travis Robben Jul 14 '16 at 04:05
  • When deseralized it should bring back the values of A, B and C as the same values when it was serialized. So they were 1, 2 and 3 when saved they should again be 1, 2 and 3 after deserialized. Therefore there is nothing wrong with your code. – Phil Wright Jul 14 '16 at 04:55
  • The setter for C is private, XmlSerializer won't tolerate it. – Travis Robben Jul 14 '16 at 05:09

3 Answers3

0

You can simply modify the getter for C like:

public int C { get { return this.A + this.B; }}
jegtugado
  • 5,081
  • 1
  • 12
  • 35
  • I appreciate the suggestion, but I'm doing more than `a+b`, and those calculations don't belong in a `get`. I only paraphrased the code to get the idea across. – Travis Robben Jul 14 '16 at 04:08
0

Deserializing will just populate the variables - any other logic required to instantiate the object needs to be run by the program, not the deserializer. Try something like this:

public class MyClass
{
    private void MyClass() // NOT just to satisfy the XML serializer
    {
        GetStuffReady();
    }

    public void MyClass(int a, int b)
    {
        A = a;
        B = b;
        GetStuffReady();
    }
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; private set; }

    public void GetStuffReady()
    {
        C = A + B;
    }

    public void DoSomeMath()
    {
        Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
    }
}

Or better yet:

public class MyClass
{
        private void MyClass() { } //just to satisfy the XML serializer
        public void MyClass(int a, int b)
        {
            A = a;
            B = b;
        }
        public int A { get; set; }
        public int B { get; set; }
        public int C
        {
            get
            {
                return A + B;
            }
            set { }
        }
        public void DoSomeMath()
        {
            Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
        }
    }

EDIT: If the variables need to be set before the logic is executed, you can create a blank instance of the class and then set the variables using a helper method that takes XML as an input. See the following answer for an example: When is the class constructor called while deserialising using XmlSerializer.Deserialize?

Community
  • 1
  • 1
Dave Smash
  • 2,941
  • 1
  • 18
  • 38
  • I tried your first method, but when the parameterless constructor is called, A and B are uninitialized, so `GetStuffReady()` fails. I don't have enough data at the time of a parameterless instantiation to perform the necessary `Stuff`. Also, the `Stuff` involves more than a simple `get` so that's out as well. – Travis Robben Jul 14 '16 at 04:21
  • why don't you just perform the expensive operation once, and memoize the result. do the calculation the first time regardless of the constructor. – Jim Jul 14 '16 at 04:28
  • You are correct - the logic is run first and then the values are set. You could try creating an empty instance and then set the variables using a helper method that takes XML as an input... Any additional logic could happen later in the same method. See this answer: http://stackoverflow.com/questions/5198431/when-is-the-class-constructor-called-while-deserialising-using-xmlserializer-des – Dave Smash Jul 14 '16 at 04:29
  • That link has just what I was looking for. A nice slick way to do what I want to do. I don't know how you found it, I did all kinds of searches for 'constructor' and 'deserialize' and 'xml' etc. If you modify your answer to include that link I will mark it as the answer. Thanks! – Travis Robben Jul 14 '16 at 04:40
  • Glad the link helped! The answer has been modified accordingly. Thanks! – Dave Smash Jul 14 '16 at 04:48
0

If you are using the regular binary formatter, then:

[OnDeserialized]
public void DoSomeMath()
{
    Console.WriteLine("{0} + {1} = {2}\n", A, B, C)
}

For the XmlSerializer, events are not supported. You could implement IXmlSerializable, but it's non trivial.

For DataContractSerializer (which serializes to xml) you could try:

[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
    ... // logic here.
}

There is an answer here to XmlSerializer but it requires inheriting the default one.
How do you find out when you've been loaded via XML Serialization?

Community
  • 1
  • 1
Jim
  • 14,952
  • 15
  • 80
  • 167