Search code examples
c#.netreflectionattributesdefault-value

Get the default value of a property given its name


I have a property, (example shown below).

 [DefaultValue(false)]
 public bool MyProperty {
    get {
       return myVal;
    }
    set {
       myVal=value;
    }
 }

The situation I'm using this is to make sure it shows up as bold in the a PropertyGrid if the default value is not set.

I find it incredibly annoying that in my constructor, I have to set the initial value of my property, and hope that they match up.

Is it possible to have my constructor "discover" the default value of a given property, and set it accordingly? Something like:

myctor()
{
   myVal = GetDefaultValueProperty<bool>("MyProperty");
}

Solution

  • You can use the following code to get the metadata you're after.

    public static T GetDefaultValue<T>(string propertyName)
    {
        var property = typeof(MyClass).GetProperty(propertyName);
    
        var attribute = property
            .GetCustomAttribute(typeof(DefaultValueAttribute)) 
                as DefaultValueAttribute;
    
        if(attribute != null)
        {
            return (T)attribute.Value;
        }
    }
    

    If you want to do something really cool, you can do this with a Lambda expression:

    public static T GetDefaultValue<T>(
        Expression<Func<T, MyClass>> propertySelector)
    {
        MemberExpression memberExpression = null;
    
        switch (expression.Body.NodeType)
        {
            case ExpressionType.MemberAccess:
                // This is the default case where the 
                // expression is simply member access.
                memberExpression 
                    = expression.Body as MemberExpression;
                break;
    
            case ExpressionType.Convert:
                // This case deals with conversions that 
                // may have occured due to typing.
                UnaryExpression unaryExpression 
                    = expression.Body as UnaryExpression;
    
                if (unaryExpression != null)
                {
                    memberExpression 
                        = unaryExpression.Operand as MemberExpression;
                }
                break;
        }
    
    
        MemberInfo member = memberExpression.Member;
    
        // Check for field and property types. 
        // All other types are not supported by attribute model.
        switch (member.MemberType)
        {
            case MemberTypes.Property:
                break;
            default:
                throw new Exception("Member is not property");
        }
    
        var property = (PropertyInfo)member;
    
        var attribute = property
            .GetCustomAttribute(typeof(DefaultValueAttribute)) 
                as DefaultValueAttribute;
    
        if(attribute != null)
        {
            return (T)attribute.Value;
        }
    }
    

    Usage is then:

    myctor()
    {
       myVal = GetDefaultValue(x => x.MyProperty);
    }