LukeHennerley
LukeHennerley

Reputation: 6444

Getting attribute of a property where the property is from an implemented interface

If I have a host of properties in an interface, but in the example I will just use one as it demonstrates what I am trying to achieve.

  interface IFoo
  {
    [Bar()]
    string A { get; set; }
  }
 class Base { }
 class Foo : Base, IFoo
 {
   public string A { get; set; }
 }

So when I do this:

Foo f = new Foo();
f.A = "Value";
Attribute b = Attribute.GetCustomAttribute(f.GetType().GetProperty("A"), typeof(Bar));

I was expecting to be able to get the instance of my Bar attribute out. Most of this is being done in a generic class and I am using my attributes for a validation model so I can't implicitly cast to an interface then get the attribute of the property in the interface because I never know what type the interface will be or what type will implement it. I need some way of getting the attribute out of my instance of Base for example.

public void GenericMethod<T>(T instance) where T : Base
{
    //Get my instance of Bar here.
}

I hope whatI am trying to do is clear, thanks in advance.

Upvotes: 1

Views: 160

Answers (2)

Andrei
Andrei

Reputation: 56716

This will give you the list of all custom attributes Bar applied to all properties in type of instance:

var attibutes = instance.GetType().GetInterfaces()
                    .SelectMany(i => i.GetProperties())
                    .SelectMany(
                        propertyInfo =>
                        propertyInfo.GetCustomAttributes(typeof (BarAttribute), false)
                    );

Is that what you are looking for?

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1064054

The property Foo.A does not have any attributes. Only IFoo.A has the attribute. You would need to use:

Attribute b = Attribute.GetCustomAttribute(typeof(IFoo).GetProperty("A"), ...);

The only other thing you can do is explicitly check the interface table via f.GetType().GetInterfaceMap(typeof(IFoo)), maybe checking each interface that is in f.GetType().GetInterfaces() that has an "A".

Something like (and this is messy):

var outerProp = f.GetType().GetProperty("A");
Attribute b = Attribute.GetCustomAttribute(outerProp, typeof(BarAttribute));
if (b == null)
{
    var candidates = (from iType in f.GetType().GetInterfaces()
                      let prop = iType.GetProperty("A")
                      where prop != null
                      let map = f.GetType().GetInterfaceMap(iType)
                      let index = Array.IndexOf(map.TargetMethods, outerProp.GetGetMethod())
                      where index >= 0 && map.InterfaceMethods[index] == prop.GetGetMethod()
                      select prop).Distinct().ToArray();
    if (candidates.Length == 1)
    {
        b = Attribute.GetCustomAttribute(candidates[0], typeof(BarAttribute));
    }
}

What this does is:

  • if the original property didn't have the attribute...
  • it checks what interfaces the type implements...
  • and sees what interface-properties the class-property implements...
  • and checks whether there is exactly one...
  • and looks for the attribute on that

Upvotes: 0

Related Questions