Search code examples
c#extension-methodscustom-attributespropertyinfo

Can an extension method be added to a class property to get the value of an attribute associated with the property?


I have several classes with attributes assigned to them. The one I'm mostly interested in is the FieldLength.MaxLength value.

/// <summary>
/// Users
/// </summary>
[Table(Schema = "dbo", Name = "users"), Serializable]
public partial class Users
{

    /// <summary>
    /// Last name
    /// </summary>
    [Column(Name = "last_name", SqlDbType = SqlDbType.VarChar)]
    private string _LastName;
    [FieldLength(MaxLength=25), FieldNullable(IsNullable=false)]
    public string LastName
    {
        set { _LastName = value; }
        get { return _LastName; }
    }

}

I need to know if it's possible to write some kind of extension method for the properties in my class to return the MaxLength value of the FieldLength attribute?

For instance. I'd like to be able to write something like the following…

Users user = new Users();
int lastNameMaxLength = user.LastName.MaxLength();

Solution

  • No. Because the syntax you propose returns the value of the LastName property and not the property itself.

    In order to retrieve and make use of the attributes, you'll need to use reflection which means you need to know the property itself.

    As an idea, you could achieve this neatly by using LINQ's Expression library though to resolve the property for the object.

    Example syntax you might look for:

    var lastNameMaxLength = AttributeResolver.MaxLength<Users>(u => u.LastName);
    

    Where:

    public class AttributeResolver
    {
        public int MaxLength<T>(Expression<Func<T, object>> propertyExpression)
        {
            // Do the good stuff to get the PropertyInfo from the Expression...
            // Then get the attribute from the PropertyInfo
            // Then read the value from the attribute
        }
    }
    

    I've found this class helpful in resolving properties from Expressions:

    public class TypeHelper
    {
        private static PropertyInfo GetPropertyInternal(LambdaExpression p)
        {
            MemberExpression memberExpression;
    
            if (p.Body is UnaryExpression)
            {
                UnaryExpression ue = (UnaryExpression)p.Body;
                memberExpression = (MemberExpression)ue.Operand;
            }
            else
            {
                memberExpression = (MemberExpression)p.Body;
            }
            return (PropertyInfo)(memberExpression).Member;
        }
    
        public static PropertyInfo GetProperty<TObject>(Expression<Func<TObject, object>> p)
        {
            return GetPropertyInternal(p);
        }
    }