5

I'm working on a documentation generator. MSDN documentation shows the parameters passed to Attributes when they are applied. Such as [ComVisibleAttribute(true)]. How would I get those parameter values and/or the constructor called in my c# code via reflection, pdb file or otherwise?

To clarify> If someone has documented a method that has an attribute on it like so:

/// <summary> foo does bar </summary>
[SomeCustomAttribute("a supplied value")]
void Foo() {
  DoBar();
}

I want to be able to show the signature of the method in my documentation like so:

Signature:

[SomeCustomAttribute("a supplied value")]
void Foo();
Charles Lambert
  • 5,042
  • 26
  • 47
  • Are you asking about coding up your own attribute that takes parameters, or are you looking to find out through reflection the way someone else's attribute has been constructed? – Sergey Kalinichenko Feb 21 '13 at 22:58
  • through reflection the way someone else's attribute has been constructed – Charles Lambert Feb 21 '13 at 23:05
  • Hmm, thanks for the clarification. I apologize for misunderstanding your question. My method obviously wouldn't give that. You'd probably have to inspect the IL, but I'm not sure how to go about doing that. – p.s.w.g Feb 21 '13 at 23:13

2 Answers2

6

If you have a member for which you want to get the custom attributes and the constructor arguments, you can use the following reflection code:

MemberInfo member;      // <-- Get a member

var customAttributes = member.GetCustomAttributesData();
foreach (var data in customAttributes)
{
    // The type of the attribute,
    // e.g. "SomeCustomAttribute"
    Console.WriteLine(data.AttributeType);

    foreach (var arg in data.ConstructorArguments)
    {
        // The type and value of the constructor arguments,
        // e.g. "System.String a supplied value"
        Console.WriteLine(arg.ArgumentType + " " + arg.Value);
    }
}

To get a member, start with getting the type. There are two ways to get a type.

  1. If you have an instance obj, call Type type = obj.GetType();.
  2. If you have a type name MyType, do Type type = typeof(MyType);.

Then you can find, for example, a particular method. Look at the reflection documentation for more info.

MemberInfo member = typeof(MyType).GetMethod("Foo");
Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
  • What about class level attributes? The member part is easy. I haven't figured out how to reflect on class level attribute parameters. – jwize Feb 18 '14 at 06:04
3

For the ComVisibileAttribute, the parameter passed to the constructor becomes the Value property.

[ComVisibleAttribute(true)]
public class MyClass { ... }

...

Type classType = typeof(MyClass);
object[] attrs = classType.GetCustomAttributes(true);
foreach (object attr in attrs)
{
    ComVisibleAttribute comVisible = attr as ComVisibleAttribute;
    if (comVisible != null)
    {
        return comVisible.Value // returns true
    }
}

Other attributes will follow a similar design pattern.


EDIT

I found this article about Mono.Cecil that describes how to do something very similar. This looks it ought to do what you need.

foreach (CustomAttribute eca in classType.CustomAttributes)
{
    Console.WriteLine("[{0}({1})]", eca, eca.ConstructorParameters.Join(", "));
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331