Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Setting a default value for C# Auto-implemented properties

4.73/5 (8 votes)
12 Jan 2012CPOL 31.4K  
After describing it so much, I felt the need to go ahead and implement it. So here goes...using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq.Expressions;using System.Reflection;namespace DefaultValue{ /// /// The...
After describing it so much, I felt the need to go ahead and implement it. So here goes...

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;

namespace DefaultValue
{
    /// <summary>
    /// The DefaultValueExtensions extends the <see cref="DefaultValueAttribute"/> to allow setting
    /// the initial value of automatic properties generically.
    /// </summary>
    public static class DefaultValueExtensions
    {
        private static Dictionary<Type, Delegate> _dctTypeInitializers = new Dictionary<Type, Delegate>();

        /// <summary>
        /// Initializes all of a type's properties by the values defined in the <see cref="DefaultValueAttribute"/>.
        /// </summary>
        /// <typeparam name="T">The type of the object to initialize properties.</typeparam>
        /// <param name="item">The item to initialize properties.</param>
        public static void InitializePropertyDefaults<T>(this T item)
        {
            Type type;
            Delegate d;
            Action<T> action;

            type = typeof(T);

            lock (DefaultValueExtensions._dctTypeInitializers)
            {
                if (!DefaultValueExtensions._dctTypeInitializers.TryGetValue(type, out d))
                    DefaultValueExtensions._dctTypeInitializers[type] = d = DefaultValueExtensions.CreateTypeInitializer(type);
            }

            action = d as Action<T>;
            action(item);
        }

        /// <summary>
        /// Creates the lambda expression to initialize the properties on the type with the default values.
        /// </summary>
        /// <param name="type">The type to initialize the properties with the default values.</param>
        /// <returns>A lambda expression to initialize the properties on the type with the default values.</returns>
        private static Delegate CreateTypeInitializer(Type type)
        {
            List<Expression> lstExpressionBody;
            ParameterExpression itemParam;

            lstExpressionBody = new List<Expression>();
            itemParam = Expression.Parameter(type, "item");

            foreach (var tuple in DefaultValueExtensions.GetPropertiesAndValues(type))
            {
                // Adds the call: item.XXXX = YYYY;
                lstExpressionBody.Add
                (
                    Expression.Assign
                    (
                        Expression.Property(itemParam, tuple.Item1),
                        Expression.Constant(tuple.Item2)
                    )
                );
            }

            // Add an empty to the end to ensure that it doesn't return a value.
            lstExpressionBody.Add(Expression.Empty());

            return Expression.Lambda(Expression.Block(lstExpressionBody), itemParam).Compile();
        }
        /// <summary>
        /// Iterates over a type's properties to list off all of the properties and the associated default values.
        /// </summary>
        /// <param name="type">The type to examine.</param>
        /// <returns>A list off all of the properties and the associated default values of a type.</returns>
        private static IEnumerable<Tuple<PropertyInfo, object>> GetPropertiesAndValues(Type type)
        {
            object[] defaultValueAttributes;
            DefaultValueAttribute defaultValueAttribute;

            foreach (PropertyInfo prop in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                defaultValueAttributes = prop.GetCustomAttributes(typeof(DefaultValueAttribute), true);

                if ((defaultValueAttributes != null) && (defaultValueAttributes.Length > 0))
                {
                    defaultValueAttribute = defaultValueAttributes[0] as DefaultValueAttribute;

                    yield return new Tuple<PropertyInfo, object>(prop, defaultValueAttribute.Value);
                }
            }
        }
    }
}


With its usage as:

C#
public MyClass()
{
    this.InitializePropertyDefaults();
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)