65.9K
CodeProject is changing. Read more.
Home

C# Automatic Property Default Value Extension Methods

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (4 votes)

Aug 23, 2011

CPOL
viewsIcon

13402

For .NET 4.0:using System;using System.Collections.Generic;using System.ComponentModel;using System.Reflection;using System.Linq.Expressions;static class AutomaticPropertyExtensions{ private static class Cache where T : class { public static readonly...

For .NET 4.0:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;

static class AutomaticPropertyExtensions
{
    private static class Cache<T> where T : class
    {
        public static readonly Action<T> Init;
        public static readonly int PropertyCount;

        static Cache()
        {
            var p = Expression.Parameter(typeof(T), "this");
            var body = Expression.Block(typeof(T)
                .ListPropertiesToReset()
                .Select(pair => Assign(p, pair.Item1, pair.Item2)));

            PropertyCount = body.Expressions.Count;
            if (PropertyCount != 0)
            {
                var result = Expression.Lambda<Action<T>>(body, p);
                Init = result.Compile();
            }
        }
    }
    
    private static Expression Assign(Expression p, PropertyInfo property, object value)
    {
        var prop = Expression.Property(p, property);
        var defaultValue = Expression.Constant(value, property.PropertyType);
        return Expression.Assign(prop, defaultValue);
    }
    
    private static IEnumerable<Tuple<PropertyInfo, object>> ListPropertiesToReset(this Type componentType)
    {
        const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

        return from PropertyInfo property in componentType.GetProperties(flags)
               where property.CanWrite
               let attributes = property.GetCustomAttributes(typeof(DefaultValueAttribute), true)
               where attributes != null && 0 != attributes.Length
               let attribute = (DefaultValueAttribute)attributes[0]
               let defaultValue = attribute.Value
               where defaultValue != null
               select Tuple.Create(property, defaultValue);
    }

    public static int ResetPropsUsingDefaultAttributes<T>(this T instance) where T : class
    {
        if (instance == null) throw new ArgumentNullException("instance");
        if (Cache<T>.Init != null) Cache<T>.Init(instance);
        return Cache<T>.PropertyCount;
    }
}
Usage:
public class TestClass
{
    [DefaultValue(0.3141)]
    public double MyPie { get; set; }

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

    public TestClass()
    {
        this.Reset();
    }

    public void Reset()
    {
        this.ResetPropsUsingDefaultAttributes();
    }

    public override string ToString()
    {
        return string.Format("MyPie = {0}, MyLove = {1}",
            MyPie, MyLove == null ? "null" : MyLove);
    }
}