Click here to Skip to main content
Click here to Skip to main content

C# Automatic Property Default Value Extension Methods

, 21 Aug 2011
Rate this:
Please Sign up or sign in to vote.
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:

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:

[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:

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:

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:

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).

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Itai Basel
Software Developer (Senior)
Israel Israel
No Biography provided

Comments and Discussions

 
Generalnice, but personally i dont like adding performance overhead... PinmemberGParkings2-Sep-11 12:48 
GeneralReason for my vote of 4 Interesting, but too slow. Slow meth... PinmemberKelqualyn22-Aug-11 22:34 
SuggestionMinor suggestion... PinmemberAndrew Rissing22-Aug-11 4:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 21 Aug 2011
Article Copyright 2011 by Itai Basel
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid