GrayFox
GrayFox

Reputation: 1089

Pass property name by lambda expression for reading attribute values

I have found this solution:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
{
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(propertyName);
    return (T)property .GetCustomAttributes(attrType, false).First();
}

Code by jgauffin from How to retrieve Data Annotations from code

I always use the extension this way:

foo.GetAttributeFrom<StringLengthAttribute>(nameof(Foo.Bar)).MaximumLength

Is there a way to pass the propertyName by using a lambda like:

foo.GetAttributeFrom<StringLengthAttribute>(f => f.Bar).MaximumLength

Thank you in advance!

Upvotes: 2

Views: 1355

Answers (2)

CodingYoshi
CodingYoshi

Reputation: 26989

The method can be like this:

public static TAtt GetAttribute<TAtt,TObj,TProperty>(this Rootobject inst, 
    Expression<Func<TObj,TProperty>> propertyExpression)
         where TAtt : Attribute
      {
         var body = propertyExpression.Body as MemberExpression;
         var expression = body.Member as PropertyInfo;
         var ret = (TAtt)expression.GetCustomAttributes(typeof(TAtt), false).First();

         return ret;
      }

If you have a class like this with the attribute:

public class Rootobject
{
  [StringLengthAttribute(10)]
  public string Name { get; set; }
}

Then you will use it like this:

var obj = new Rootobject();
         var max = obj.GetAttribute<StringLengthAttribute, Rootobject, string>((x) => x.Name)
                      .MaximumLength;

Improvements

Add error checking in case the attribute is not found or the lambda is not for a property etc.

Upvotes: 0

Hamid Pourjam
Hamid Pourjam

Reputation: 20754

You can split the work into two functions in order to bypass specifying all generic parameter type for a generic method restriction

public static object[] GetPropertyAttributes<TObject, TProperty>(
    this TObject instance,
    Expression<Func<TObject, TProperty>> propertySelector)
{
    //consider handling exceptions and corner cases
    var propertyName = ((PropertyInfo)((MemberExpression)propertySelector.Body).Member).Name;
    var property = instance.GetType().GetProperty(propertyName);
    return property.GetCustomAttributes(false);
}

public static T GetFirst<T>(this object[] input) where T : Attribute
{
    //consider handling exceptions and corner cases
    return input.OfType<T>().First();
}

then use it like

foo.GetPropertyAttributes(f => f.Bar)
   .GetFirst<StringLengthAttribute>()
   .MaximumLength;

Upvotes: 3

Related Questions