"The Joy of a Custom Built Object" or "What the heck is DoFinalConstruction()?"

Updated 5/2/07: After Orcas beta 1 this mechanism has been changed as described in this post .

______________________ 

 

Here’s another interesting question that was raised in the ADO.Net Tech Preview forum: How do I add custom construction logic to my entity without creating another constructor overload?

 

This question is particularly interesting because the code generator automatically creates parameterless constructors for all entities so you could find yourself thinking crazy thoughts like “do I put in a dummy parameter just so that I can have another overload?” or “should I modify the output of the codegen instead of just defining my own partial class?”.  Yes, these thoughts are crazy, and the answer to both questions is definitely “No.”

 

The way you deal with this is to create an override for the method DoFinalConstruction.  In order to play nicely in the sandbox with other classes in your entity’s inheritance chain, this method should be called by all constructors but only when the constructor is executing on the most derived type.  Further, your implementation must call the base DoFinalConstruction in order to make sure everyone gets a chance to execute their custom logic.  The generated code obeys these rules.  So if you are not creating a new constructor, all you need to do is add an override for this method to your partial class and make sure that override calls the base.

 

Example: I have an Actor entity which has a guid for its key value, and I want the guid to be generated automatically whenever new instances of the object are constructed to simplify working with the object model.  I just need to create a partial class for the Actor object which looks like this:

 

    partial class Actor

    {

        new protected void DoFinalConstruction()

        {

            // only set the ID if it hasn't already been set

            // this way we won't overwrite it if someone calls a

            // constructor overload with it as a parameter

            if (this.ID == Guid.Empty)

            {

                this.ID = Guid.NewGuid();

            }

            // don't forget to call base.DoFinalConstruction or

            // else someone up the chain from me might have some

            // construction logic that gets skipped

            base.DoFinalConstruction();

        }

    }

 

If I want to add a constructor override of my own (maybe to take a single required property as the parameter), then I need to make sure I follow the appropriate pattern in my constructor as well:

 

        public Actor(string name) : base()

        {

            this.Name = name;

            // call DoFinalConstruction, but only if we are the

            // constructor for the exact type being created (not

            // something it inherits from)

            if ((((object)(this)).GetType() == typeof(Actor)))

            {

                this.DoFinalConstruction();

            }

        }

 

While maybe not as fancy as a custom built home, custom built objects can be fun too…

 

- Danny