h bob
h bob

Reputation: 3780

Get Attribute from object

I want to get a specific Attribute on one of an object's properties.

I used this code as a starter:

public static class ObjectExtensions {
  public static MemberInfo GetMember<T,R>(this T instance, 
    Expression<Func<T, R>> selector) {
      var member = selector.Body as MemberExpression;
      if (member != null) {
        return member.Member;
      }
      return null;
  }

public static T GetAttribute<T>(this MemberInfo meminfo) where T : Attribute {
  return meminfo.GetCustomAttributes(typeof(T)).FirstOrDefault() as T;
  }
}

Which you then call like this:

var attr = someobject.GetMember(x => x.Height).GetAttribute<FooAttribute>();

But I'd like it in one clean step like this:

var attr = someobject.GetAttribute<FooAttribute>(x => x.Height);

How do I combine those two functions to give this signature?

Update: Also, why does this not work for enums?

Upvotes: 0

Views: 159

Answers (1)

just.another.programmer
just.another.programmer

Reputation: 8785

You won't be able to get that exact signature. For the method to work, it needs three generic type arguments (one for the object type T, one for the attribute type TAttribute, and one for the property type TProperty). T and TProperty can be inferred from usage, but TAttribute needs to be specified. Unfortunately, once you specify one generic type argument, you need to specify all three of them.

public static class ObjectExtensions {
    public static TAttribute GetAttribute<T, TAttribute, TProperty> (this T instance, 
        Expression<Func<T, TProperty>> selector) where TAttribute : Attribute {
        var member = selector.Body as MemberExpression;
        if (member != null) {
            return member.Member.GetCustomAttributes(typeof(TAttribute)).FirstOrDefault() as TAttribute;
        }
        return null;
    }
}   

This is why the two methods in the question were separate to begin with. It's easier to write

var attr = someobject.GetMember(x => x.Height).GetAttribute<FooAttribute>();

than to write

var attr = someobject.GetAttribute<Foo, FooAttribute, FooProperty>(x => x.Height);

Upvotes: 2

Related Questions