81

I need to be able to read the value of my attribute from within my Method, how can I do that?

[MyAttribute("Hello World")]
public void MyMethod()
{
    // Need to read the MyAttribute attribute and get its value
}
Mafii
  • 7,227
  • 1
  • 35
  • 55
Coppermill
  • 6,676
  • 14
  • 67
  • 92
  • There are also generic version (you dont need casting!) of these methods implemented as extensions in newer versions of .net (I think after 4.0), so visitors, check out the answers other than the accepted one – Mafii Jul 03 '17 at 08:37

6 Answers6

96

You need to call the GetCustomAttributes function on a MethodBase object.
The simplest way to get the MethodBase object is to call MethodBase.GetCurrentMethod. (Note that you should add [MethodImpl(MethodImplOptions.NoInlining)])

For example:

MethodBase method = MethodBase.GetCurrentMethod();
MyAttribute attr = (MyAttribute)method.GetCustomAttributes(typeof(MyAttribute), true)[0] ;
string value = attr.Value;    //Assumes that MyAttribute has a property called Value

You can also get the MethodBase manually, like this: (This will be faster)

MethodBase method = typeof(MyClass).GetMethod("MyMethod");
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
37
[MyAttribute("Hello World")]
public int MyMethod()
{
var myAttribute = GetType().GetMethod("MyMethod").GetCustomAttributes(true).OfType<MyAttribute>().FirstOrDefault();
}
EgorBo
  • 6,120
  • 3
  • 35
  • 40
28

The available answers are mostly outdated.

This is the current best practice:

class MyClass
{

  [MyAttribute("Hello World")]
  public void MyMethod()
  {
    var method = typeof(MyClass).GetRuntimeMethod(nameof(MyClass.MyMethod), Array.Empty<Type>());
    var attribute = method.GetCustomAttribute<MyAttribute>();
  }
}

This requires no casting and is pretty safe to use.

You can also use .GetCustomAttributes<T> to get all attributes of one type.

b-rad15
  • 89
  • 1
  • 2
  • 13
Mafii
  • 7,227
  • 1
  • 35
  • 55
1

If you store the default attribute value into a property (Name in my example) on construction, then you can use a static Attribute helper method:

using System;
using System.Linq;

public class Helper
{
    public static TValue GetMethodAttributeValue<TAttribute, TValue>(Action action, Func<TAttribute, TValue> valueSelector) where TAttribute : Attribute
    {
        var methodInfo = action.Method;
        var attr = methodInfo.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
        return attr != null ? valueSelector(attr) : default(TValue);
    }
}

Usage:

var name = Helper.GetMethodAttributeValue<MyAttribute, string>(MyMethod, x => x.Name);

My solution is based on that the default value is set upon the attribute construction, like this:

internal class MyAttribute : Attribute
{
    public string Name { get; set; }

    public MyAttribute(string name)
    {
        Name = name;
    }
}
Mikael Engver
  • 4,634
  • 4
  • 46
  • 53
0

In case you are implementing the setup like @Mikael Engver mentioned above, and allow multiple usage. Here is what you can do to get the list of all the attribute values.

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCase : Attribute
{
    public TestCase(string value)
    {
        Id = value;
    }

    public string Id { get; }        
}   

public static IEnumerable<string> AutomatedTests()
{
    var assembly = typeof(Reports).GetTypeInfo().Assembly;

    var methodInfos = assembly.GetTypes().SelectMany(m => m.GetMethods())
        .Where(x => x.GetCustomAttributes(typeof(TestCase), false).Length > 0);

    foreach (var methodInfo in methodInfos)
    {
        var ids = methodInfo.GetCustomAttributes<TestCase>().Select(x => x.Id);
        yield return $"{string.Join(", ", ids)} - {methodInfo.Name}"; // handle cases when one test is mapped to multiple test cases.
    }
}
Hoang Minh
  • 1,066
  • 2
  • 21
  • 40
0

I used this method :

public static TAttributeMember? GetMethodAttributeValue<TAttribute, TAttributeMember>(Expression<Func<object>> property, Func<TAttribute, TAttributeMember> valueSelector) where TAttribute : Attribute
{
    var methodInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
    var attr = methodInfo?.GetCustomAttributes(typeof(TAttribute), true).FirstOrDefault() as TAttribute;
    return attr != null && valueSelector != null ? valueSelector(attr) : default(TAttributeMember);
}
    

Then can use like this:

var group = GetMethodAttributeValue<FieldAttribs, FieldGroups>(() => dd.Param2, a => a.Group);
MohsenB
  • 1,669
  • 18
  • 29