Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# Automatic Property Default Value Extension Methods

0.00/5 (No votes)
21 Aug 2011 1  
This article shows how to automatically initialize/reset automatic properties' default values.

Automatic properties are great but the annoyance of not being able to set them automatically deters a lot of people from using them.
What we (read - I) want to be able to do is something like this:


C#
double MyPie { get; set; } = "3.141";
string MyLove { get; set; } = "Pizza";

The default value attribute in System.ComponentModel is of no help there, though a lot of us (read - me) tried that in the beginning:


C#
[DefaultValue(0.3141)]
double MyPie { get; set; }

[DefaultValue("Pizza")]
string MyLove { get; set; }

Initializing the properties one by one in the constructor is at least as annoying as simply doing this:


C#
double _myPie = 0.3141;
double MyPie { get { return _myPie; } set { _myPie = value; } }

double _myLove = "Pizza";
double MyLove { get { return _myLove; } set { _myLove = value; } }

Luckily, the nice little feature of extension methods allows us something not exactly optimal or fully elegant - but functional and a good exercise in C# clockwork.
So with just a bit of hammering, we can enable automatic reset properties to their declared System.ComponentModel.DefaultValueAttribute if any was specified.
Here is some test code:


C#
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;

using CSharpUtils;
namespace MyAppNamespace
{
  public class TestClass
  {
    [DefaultValue(0.3141)]
    public double MyPie { get; set; }

    [DefaultValue("Pizza")]
    public string MyLove { get; set; }

    public TestClass()
    {
      MessageBox.Show(string.Format("MyPie = {0}, MyLove = {1}", 
                      MyPie, MyLove == null ? "null" : MyLove));
      int ret = (this as Object).ResetPropsUsingDefaultAttributes(false);
      MessageBox.Show(string.Format(
                      "MyPie = {0}, MyLove = {1}. {2} properties we set", 
                      MyPie, MyLove == null ? "null" : MyLove, ret));
      MyLove = "My dear wife";
      MessageBox.Show(string.Format("MyPie = {0}, MyLove = {1}", 
                      MyPie, MyLove == null ? "null" : MyLove));
      ret = (this as Object).ResetPropsUsingDefaultAttributes(false);
      MessageBox.Show(string.Format(
                      "MyPie = {0}, MyLove = {1}. {2} properties we set", 
                      MyPie, MyLove == null ? "null" : MyLove, ret));
    }
  }
}

This (as you may have already guessed) is done using an extension method to the System.Object class.
You will need a public static class to define the extension method in. Here's the basic implementation source:


C#
using System;
using System.Text;
using System.Reflection;
using System.ComponentModel;

namespace CSharpUtils
{
  static class CSharpUtilsExtensionMethods
  {
    public static int ResetPropsUsingDefaultAttributes(
           this Object oThis, bool initInheritedProperties)
    {
      int count = 0;
      //BindingFlags.Static
      Type oType = oThis.GetType();
      PropertyInfo[] infos = oType.GetProperties(BindingFlags.NonPublic | 
                     BindingFlags.Public | BindingFlags.Instance);
      foreach (PropertyInfo inf in infos)
      {
        if (initInheritedProperties || inf.DeclaringType.Equals(oType))
        {
          object[] oDefAtts = inf.GetCustomAttributes(
            typeof(DefaultValueAttribute), initInheritedProperties);
          if (oDefAtts.Length > 0)
          {
            DefaultValueAttribute defAtt = 
                 oDefAtts[oDefAtts.Length - 1] as DefaultValueAttribute;
            if (defAtt != null && defAtt.Value != null && 
                !defAtt.Value.Equals(inf.GetValue(oThis, 
                 BindingFlags.GetProperty, null, null, null)))
            {
              inf.SetValue(oThis, defAtt.Value, BindingFlags.SetProperty, 
                           null, null, null);
              count++;
            }
          }
        }
      }
      return count;
    }
  }
}

All that's left now is using our test class (here again - with no message box and other nonsense).


C#
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;

using CSharpUtils;
namespace MyAppNamespace
{
  public class TestClass
  {
    [DefaultValue(0.3141)]
    public double MyPie { get; set; }

    [DefaultValue("Pizza")]
    public string MyLove { get; set; }


    public void ResetProps()
    {
      (this as Object).ResetPropsUsingDefaultAttributes(false);
    }
    public TestClass()
    {
      ResetProps();
    }
  }
}

Notes:



  • To use the extension method, the .cs file making the call must have a 'using' declaration of the namespace where the extension method resides in.
  • Passing true for the parameter initInheritedProperties also initializes any parent class properties - at the expense of possibly resetting already initialized properties. You can always extend the extension method to try and account for these cases.
  • Resetting the properties in this manner also works outside the constructor - anywhere in the program with proper access.
  • There's still the annoyance of having to add a line in the constructor - but it is just one line and will not require additional modifications if properties are added, removed, or their type/default value is changed.

There you go, have fun.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here