How to get custom method attributes from Action <T>?
How to get custom method attributes from Action<T> ?
Example:
//simple custom attribute public class StatusAttribute : Attribute { public StatusAttribute() { Message = ""; } public string Message { get; set; } } // an extension methodto wrap MethodInfo.GetCustomAttributes(Type, Bool) with // generics for the custom Attribute type public static class MethodInfoExtentions { public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(this MethodInfo methodInfo, bool inherit) where TAttribute : Attribute { object[] attributeObjects = methodInfo.GetCustomAttributes(typeof(TAttribute), inherit); return attributeObjects.Cast<TAttribute>(); } } // test class with a test method to implment the custom attribute public class Foo { [Status(Message="I'm doing something")] public void DoSomething() { // code would go here } } // creates an action and attempts to get the attribute on the action private void CallDoSomething() { Action<Foo> myAction = new Action<Foo>(m => m.DoSomething()); IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true); // Status Attributes count = 0? Why? } I understand that I can do this using reflection in Foo, but for what I'm trying to create, I have to use Action<T> .
The problem is that the action does not directly point to Foo.DoSomething - it points to the method generated by the form compiler:
private static void <>__a(Foo m) { m.DoSomething(); } One option is to change it to Expression<Action<T>> , after which you can parse the expression tree and extract the attributes:
Expression<Action<Foo>> myAction = m => m.DoSomething(); var method = ((MethodCallExpression)myAction.Body).Method; var statusAttributes = method.GetCustomAttributes<StatusAttribute>(true); int count = statusAttributes.Count(); // = 1 The problem is that lambda m => m.DoSomething() does not match DoSomething . This is a lambda expression that compiles into a method call on a compiler-generated method, possibly using the type generated by the compiler (although it may not be the last, since there are no captured local variables).
A very complicated way to get an Action<Foo> from an instance of a (non-static) method of type Foo :
var myAction = (Action<Foo>)Delegate.CreateDelegate( typeof(Action<Foo>), null, // treat method as static, even though it not typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public) ); Obviously, this is far from ideal and probably practically useless in your case; but it is worth knowing;)
Refresh . Actually, it just occurred to me that you could write a quick extension method to make it simple for any instance method that you want to wrap as a static method (and keep the "correct" MethodInfo ):
public static class ActionEx { public static Action<T> ToStaticMethod<T>(this Action action) { if (!(action.Target is T)) { throw new ArgumentException("Blah blah blah."); } return (Action<T>)Delegate.CreateDelegate( typeof(Action<T>), null, action.Method ); } } This will allow you to do:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>(); Admittedly, this is not as good as m => m.DoSomething() ; but it gives you an Action<T> , the Method property actually refers to the DoSomething method.
Alternatively, instead of Action<T> you can use Expression<Action<T>> and get MethodInfo from this. Note that the syntax looks the same in this case:
Action<Foo> myAction = m => m.DoSomething(); Expression<Action<Foo>> myExpression = m => m.DoSomething(); But this is a complex proposition, since an arbitrary Expression<Action<T>> not guaranteed as simple as m => m.DoSomething() .
None of the previous answers (except Marc, which has no user code) seems to be compiling :)
So, I would suggest mine:
private static void CallDoSomething() { var f = new Foo(); Action myAction = f.DoSomething; IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true); }