Using Inheritance to Extend AspDotNetStorefront Code

How To:  Using Inheritance to Extend AspDotNetStorefront Code

Applies To: Any custom project that requires extending vendor code

Scenario:   You are building a custom feature for AspDotNetStorefront.  The built-in objects provide most of the properties and methods you need, but are missing a few things.  What is the best method to go about adding the additional information?

Solution:

I’ll preface this by stating that this is not a complete guide to using inheritance.  There are many, many resources covering the topic since it is fundamental to object oriented programming.  With it being such a basic concept however, I am surprised at how rarely I see it used when a core object in a vendor’s application needs to be extended.  This article demonstrates a scenario where inheritance was used instead of modifying vendor code or creating entirely new objects to save hours of labor and hundreds of lines of code.

Working with third-party code represents unique challenges to a software developer responsible for customizing it to meet the client’s needs, the biggest of these being vendor upgrades.  Inevitably the client is going to want new features or compatibility updates in later versions of the vendor’s software, and the manner in which your modifications are made are going to determine the quality of life and useful lifespan that the project manager quoting the upgrade is going to enjoy.  Although not always feasible or appropriate, use of inheritance is one way you can segregate your custom code from vendor code while greatly reducing the effort required during upgrades and preventing the duplication of code that (mostly) already exists.

Let’s start with a real-world example that I ran across while refactoring our alpVibe In-Stock Notification add-on.  In keeping with good development standards I determined that it was right and proper to move the code responsible for sending the emails from the product variant and inventory management pages into a custom class library since it also needed to be accessible from WSI.  I needed to write routines that accepted a variant ID and some other parameters, customized an email, and sent it to each person on a list stored in a database table.  Sounds simple enough until you add in the fact that all of the emails need to be sent asynchronously without any callbacks and the database table needs to be updated atomically as each message is sent.  Oh yeah, and each customer can have multiple records in the table, so just updating every record with that email address won’t work.  We need to know exactly which record to update as each email is sent. 

In the interest of self-disclosure, I am a huge fan of using generic lists of complex objects as parameters to make my methods smaller and easier to follow.  Loops can be hard enough to follow as is… no sense in making them any larger than they need to be by cluttering them up with unnecessary method calls and logic.  This particular project was an ideal candidate for this practice since each send operation could consist of any number emails, each with a unique recipient, subject, and message body.  Even better, AspDotNetStorefront already has an Email object that has all of the properties one would need.  Just create a routine that instantiates all of the email objects and returns it as a neatly packaged generic list and all that is left to do is watch clips of Irish riverdancing on YouTube while nursing the last few cherished ounces of the day’s seventh Mountain Dew.

Just before I disabled the recline lock on my desk chair I realized I had forgotten something…  there was that table that needed to be updated once the emails went out to prevent the same customer from being spammed over and over again.  There are any number of things that can cause an email to fail, probably making it one of the most unreliable things that a website can do, so I wanted to update the table as each individual email successfully reached the outgoing mail server (what happens from there is an act of providence).  Worse, this was all being executed asynchronously with no return value, meaning I was not going get a list of successfully sent emails back.  The Email objects that I was sending over to my mail send routine knew nothing about in-stock notifications and the tables that in which their underlying data was stored.  I fell into despair.

At this point there were several options (none of which got my any closer to my YouTube videos, and my Mountain Dew was now empty).  I could crack open the AspDotNetStorefront source code and add a few properties to the Email object, I could forget about the AspDotNetStorefront Email object and create my own, I could ditch the idea of passing Emails around altogether and come up with another way to handle it, rig up some kind of callback, and so on.  Option 1 was not very attractive since I would be relegating myself to moving modifications from version to version for the rest of eternity, and the other options seemed like an awful lot of coding when all I needed was a couple extra integers.

It is exactly in scenarios like this where class inheritance really shines.  By creating my own custom object that inherited from the AspDotNetStorefront Email object all that was needed was to add my extra properties and finish the project.   Instead of writing a couple hundred lines of code, I was able to fulfill my needs with one single class containing exactly 3 lines of code (if you leave out my comments and line breaks).  That was it… 3 lines.

So how was it done?  Since the alpVibe In-Stock Notification add-on is copyrighted intellectual property of Alynnlee Productions, Inc. I am not going to re-post the code here, but we’ll create our own example class that does basically the same thing.

We start by creating a new class called MyEmail.  It can be in any namespace you want (we’re going to use CustomObjects), either in an assembly or in App_Code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; 

namespace CustomObjects
{
    /// <summary>
    /// Summary description for MyEmail
    /// </summary>
    public class MyEmail
    {
        public MyEmail()
        {
            //
            // TODO: Add constructor logic here
            //
        }
    }
}


Next, lets inherit the class from the AspDotNetStorefront Email Object.  We do this with a colon next to the class name, and beside it we put the name of the class we are inheriting.

    public class MyEmail : AspDotNetStorefrontCore.EMail
    {
        public MyEmail()
        {
        }

    }


This is important.  When inheriting a class, all of your class constructors must have a corresponding constructor with the same signature in the parent class.  If your parent class has a single constructor that takes String, String, int, then your new child class’ constructor must take String, String, int.  When you call your constructor, the base class constructor with the corresponding signature fires first and then any additional logic you have included in your constructor.  In this case, the AspDotNetStorefrontCore.Email object has a constructor that takes no arguments and has no logic, so there is nothing left to do.

Next we add our custom properties and methods.  Notice that I am using default getters and setters here to save a little bit of time as well.

    /// <summary>
    /// Summary description for MyEmail
    /// </summary>
    public class MyEmail : AspDotNetStorefrontCore.EMail
    {
        public MyEmail() { } 

        public String MyCustomStringProperty { get; set; } 

        public int MyCustomIntProperty { get; set; } 

        public bool IsInheritanceAwesome { get { return true; } } 

        public void DoStuff()
        {
            int i = 1;
            return;
        }
    }


Now comes the cool part.   When we instantiate a new instance of our MyEmail object, not only will you have access to the properties and methods we have defined above, but we also have access to all of the underlying AspDotNetStorefrontCore.EMail properties and methods as well.  Since you can’t see my intellisense, here is an example of what it looks like when you are working with it:

    public static class MyLogic
    {
        public static void CreateEmail()
        {
            MyEmail eml = new MyEmail(); 

            eml.EmailAddress = "user@domain.com";
            eml.FirstName = "Jane";
            eml.LastName = "Doe";
            eml.FromAddress = "sender@company.com";
            eml.FromName = "Joe";
            eml.IncludeFooter = true;
            eml.MailSubject = "Irish river dance";
            eml.MailContents = "Hi Jane, Did you get the link I sent you earlier?";

            eml.MyCustomIntProperty = 1;
            eml.MyCustomStringProperty = "Hey, this is a custom property!"; 

            bool developerDeservesABonus = eml.IsInheritanceAwesome; 

            eml.DoStuff();
        }
    }


As you can see, I had access to the properties and methods from both the parent object and the child object.  By using inheritance I saved myself hundreds of lines of code and hour after hour of maintaining modifications over the course of an undefined number of future upgrades.   My methods were short and easy to understand, my emails were sent, my tables were updated, and everyone was happy.  As long as AspDotNetStorefront doesn’t substantially change the way the Email object functions, my code will move from version to version ad infinitum with zero changes to either the custom code or the vendor’s application.

This was obviously a simple example, but hopefully one that shows how useful inheritance can be when you need it. 

Article ID: 13, Created On: 4/17/2012, Modified: 4/17/2012