(Full Source Code Available at the end of this article)

The basic idea is simple enough – you have a type (class) with certain properties that is being used by various consumers.  The type represents some entity – say ‘Employee’. Let us assume that all your employees were in India – where they do not have Social Security Numbers.  Recently though, your company hired employees in the U.S.  – and now, your employee type needs to support a SSN field.  You need to add an additional property (SSN) to your ‘Employee’ type. Ordinarily, this would mean:

  1. Modification (and recompilation) of your Server Side Object (Employee class).
  2. Re-Deployment of the server side assemblies containing the Employee class.
  3. Modification of all clients using the object to consume the new property.

That is obviously, a lot of work, for a simple change to a single domain object (the Employee class).  What we need instead, is a way for us to support such additional properties without modifying the server side object – and with minimal changes to the client code.  It is instructive to start with the Client – and what we expect the client code to do.

The Code (Client) – what do we want each client to be able to do?

// This is all that the client should need to do – add the new SSN property to an existing collection of properties.
Employee empl = new Employee();
empl.Properties["SocialSecurityNumber"].Value = "123456789";

Now  that we have an idea of what we expect the client code do, we can start looking at what the server side object needs in order to support this.

The Code (server side Employee class) – what do we need to change in the Employee class to accommodate the PropertyBag?

The main change to our Employee type is to add a member level variable for storing the PropertyBag collection. We use Composition (as shown below) to add an instance of the PropertyBag class to our Employee class:

        // START Everything you need to add to the Employee class to make it handle PropertyBags
        private PropertyBag _properties; // COMPOSITION

        public PropertyBag Properties
        {
            get { return _properties; }
            set { _properties = value; }
        }

        public Employee()
        {
            this._properties = new PropertyBag();
        }
        // END Everything you need to add to the Employee class to make it handle PropertyBags

 

The Code (The PropertyBag class) – what does the PropertyBag class look like?

We use a HashTable to store property names and property values. A simple Indexer (public Property this[string name]), acts as the lookup for a specific property. It accepts a string (name of the property) and returns the entire Property object (name-value pair).

public class PropertyBag
    {
        private Hashtable _propertyBag = new Hashtable();
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

      
        // Indexer which takes the name of the property and retrieves it from the PropertyBag  
        public Property this[string Name]
        {
            get
            {
                Property prop;
                // if a property with this name already exists, return it     
                if (_propertyBag.Contains(Name))
                    prop = (Property)_propertyBag[Name];
                else // else, create a new property with this name
                {
                    prop = new Property(Name);
                    _propertyBag.Add(Name, prop);
                }
                return prop;
            }
        }

         public class Property : System.Object
         {
               private string _name;                         // name of property
               private System.Object _value;                 // value of property

                public System.Object Value
                {
                  get { return _value; }
                  set{
                      // ensure thread safety
                      lock(this)
                      {                          
                          _value = this.GetType().GetProperty(_name);
                      }
                    }
                }
         
               public Property(string _inName)
               {
                    this._name = _inName;  
               }
         }
    }

With just these simple classes PropertyBag and Employee class that uses PropertyBags, we arrive at a solution which lets us add new properties without requiring re-deployment of server side code.  The above design works great if we build it into our original design. What if our product has already shipped – and we did not implement PropertyBags ?

What if our product is already deployed – Is it still possible to add PropertyBags after deployment?

Yes – with the caveat that you will need a one time re-deployment of the new server side assemblies containing the modified Employee type. However, the good news is that none of the existing clients will be affected by this modification (i.e. none of the clients will break) since the only change we made was adding a new class level member (PropertyBags) to the Employee type.

Summary

Property bags are extremely useful constructs that allow the ability to dynamically expand the (list of) properties that a given type supports. Using a simple hashtable for defining the PropertyBag and composition for including it within your original type (Employee), we have a powerful construct allowing us to change the type after we have already shipped and deployed it.  If you thought about exposing this PropertyBag when your original class design took place, you would have saved yourself a lot of trouble. You do not have to worry about recompiling and re-deploying your server side code. Even if your code is already deployed/in production, you can still add PropertyBags without breaking any of the clients using the type. The newly compiled version of your type (Employee along with PropertyBag) will need to be made available to the clients interested in using your propertyBag.

Future Thought(s)

In addition to using the PropertyBag to expand the list of properties, how about using it to expand the list of capabilities (methods) exposed by a type?

Anuj holds professional certifications in Google Cloud, AWS as well as certifications in Docker and App Performance Tools such as New Relic. He specializes in Cloud Security, Data Encryption and Container Technologies.

Initial Consultation

Anuj Varma – who has written posts on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.