Marco Mangia
Marco Mangia

Reputation: 164

Reflecting on property to get attributes. How to do when they are defined elsewhere?

I have a class Bar like this:

class Foo : IFoo {
  [Range(0,255)]
  public int? FooProp {get; set}
}

class Bar : IFoo
{
  private Foo foo = new Foo();
  public int? FooProp { get { return foo.FooProp; }
                       set { foo.FooProp= value; } } 
}

I need to find the attribute [Range(0,255)] reflecting ONLY on the property Bar.FooProp. I mean, the prop is decorated in the class instance (.. new Foo()) not in the class when I am currently parsing. Infact Bar.FooProp has no attributes

EDIT

I moved attributes on the interface's definition, so what I have to do is parsing the inherited interfaces to find them. I can do that because Bar class must implement IFoo.In this particular case, I'm lucky, but the problem remains when I have no interfaces... I will take note for the next time

foreach(PropertyInfo property in properties)
{
  IList<Type> interfaces = property.ReflectedType.GetInterfaces();
  IList<CustomAttributeData> attrList;
  foreach(Type anInterface in interfaces)
  {
    IList<PropertyInfo> props = anInterface.GetProperties();
    foreach(PropertyInfo prop in props)
    {
      if(prop.Name.Equals(property.Name))
      { 
        attrList = CustomAttributeData.GetCustomAttributes(prop);
        attributes = new StringBuilder();
        foreach(CustomAttributeData attrData in attrList)
        {
            attributes.AppendFormat(ATTR_FORMAT,
                                        GetCustomAttributeFromType(prop));
        }
      }
    }
  }

Upvotes: 4

Views: 2914

Answers (2)

Emperor XLII
Emperor XLII

Reputation: 13452

I had a similar situation a while back where I had an attribute declared on a method in an interface, and I wanted to get the attribute from a method on a type implementing the interface. For example:

interface I {
  [MyAttribute]
  void Method( );
}

class C : I {
  void Method( ) { }
}

The code below is used to check all of the interface implemented by the type, see which interface members the given method implements (using GetInterfaceMap), and returns any attributes on those members. Right before this, I also check if the attribute is present on the method itself.

IEnumerable<MyAttribute> interfaceAttributes =
  from i in method.DeclaringType.GetInterfaces( )
  let map = method.DeclaringType.GetInterfaceMap( i )
  let index = GetMethodIndex( map.TargetMethods, method )
  where index >= 0
  let interfaceMethod = map.InterfaceMethods[index]
  from attribute in interfaceMethod.GetCustomAttributes<MyAttribute>( true )
  select attribute;

...

static int GetMethodIndex( MethodInfo[] targetMethods, MethodInfo method ) {
  return targetMethods.IndexOf( target =>
         target.Name == method.Name
      && target.DeclaringType == method.DeclaringType
      && target.ReturnType == method.ReturnType
      && target.GetParameters( ).SequenceEqual( method.GetParameters( ), PIC )
  );
}

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1064014

When looking at FooProp, there is nothing to identify the existence of a Foo (at any point). Perhaps you could add an attribute to identify the foo field, and reflect on that (via FieldInfo.FieldType)?

Upvotes: 1

Related Questions