3

I am serializing objects to XML using System.Xml.Serialization and this requires me to have parameterless constructors.

I am therefore trying to use Object Initialization Syntax to assign values to certain properties and then use the constructor logic to format these values as needs be before I serialize the objects to XML.

My problem is that the constructor runs before the properties are assigned their values. A simplified example is below:

class Program
{
    static void Main(string[] args)
    {
        Foo myFoo = new Foo() { HelloWorld = "Beer", HelloWorldAgain = "More beer" };

        Console.WriteLine(myFoo.HelloWorld);
        Console.WriteLine(myFoo.HelloWorldAgain);

        Console.ReadLine();
    }
}

public class Foo : Bar
{
    public string HelloWorld { get; set; }

    public Foo()
    {
        Console.WriteLine("Foo Was Initialized");
        Console.WriteLine(HelloWorld);
    }
}

public abstract class Bar
{
    public string HelloWorldAgain { get; set; }

    public Bar()
    {
        Console.WriteLine("Bar was initialized");
        Console.WriteLine(HelloWorldAgain);
    }
}

This results in the following output:

Output

As you can see the constructor logic runs, and then the properties are assigned values. I need this to work the other way around.

Is this possible?

JMK
  • 27,273
  • 52
  • 163
  • 280
  • What sort of pre-serialisation formatting are you intending doing? – Eric Smith Jun 20 '12 at 18:21
  • I'm passing in an ID and then running queries against a database to pull back various pieces of information, and assign these pieces of information to automatic properties, and I figured it would be tidier to do this within the constructor – JMK Jun 20 '12 at 18:23

4 Answers4

6

Serialization requires you to have a parameterless constructor, but does not limit you to that one constructor.

Keep the no-arg constructor for deserialization, but add another constructor that takes your values and does the required initialization when you need to instantiate the class in code.

Object initialization syntax is just shorthand for setting properties after construction.

Jay
  • 56,361
  • 10
  • 99
  • 123
5

No. Object initialization syntax is just a shortcut. When you write:

Foo foo = new Foo { HelloWorld  = "Beer" };

The compiler just rewrites this to something very close to what happens if you write:

Foo foo = new Foo();
foo.HelloWorld  = "Beer";

If the parameters are required in order for your object to exist, you should put them as arguments in the constructor.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • XML serialization does require there to be a parameterless public constructor, but you can have other constructor overloads as you suggest for API consumers. – Chris Sinclair Jun 20 '12 at 18:13
  • 6
    @Reed, to be pedantic, [it's not *exactly* the same](http://stackoverflow.com/questions/1679780/when-using-object-initializers-why-does-the-compiler-generate-an-extra-local-va) as what you wrote. – Kirk Woll Jun 20 '12 at 18:23
  • @KirkWoll Very true - I edited the language - It's just conceptually similar as a mental model, but yes, it's not exactly the same ;) – Reed Copsey Jun 20 '12 at 18:44
2

No it's not possible, cause in order to be able to initialize a property of the object, object has already exist. It's existance is guranteed by ctor running before all other stuff.

If we are talking about "not running default constructor", like a conceptual question. You can do that by using a static property. In that case Foo() will not be called. But it's naturally out of the current question subject.

Tigran
  • 61,654
  • 8
  • 86
  • 123
1

Arguably, the syntax is deceptive. What is happening here?

var myFoo = new Foo();
myFoo.HelloWorld = "Beer";
myFoo.HelloWorldAgain = "MoreBeer";

That's it, I'm afraid. It's simply not possible to initialise properties before the constructor has run. The constructor is the first thing that 'happens' after memory for the object is allocated and default values are assigned to fields.

BTW, you don't need the parens using the object initialisation syntax. This would be just as good (but even more deceptive):

var myFoo = new Foo { HelloWorld = "Beer", HelloWorldAgain = "MoreBeer" };

Looking at your question, it looks like what you're trying to do (modify the properties before serialisation) doesn't belong in the constructor.

Eric Smith
  • 5,262
  • 2
  • 33
  • 49