Can I get a method attribute from a generic delegate? - c#

I'm sure there's an answer already on the forum somewhere, but I haven't been able to find it so far. As per this example I am using anonymous methods in conjunction with a delegate in order to have different methods with the different parameters but the same return type all work as function parameters:
public delegate TestCaseResult Action();
...
[TestDescription("Test whether the target computer has teaming configured")]
public TestCaseResult TargetHasOneTeam()
{
// do some logic here and return
// TestCaseResult
}
[TestDescription("Test whether the target computer has the named team configured")]
public TestCaseResult TargetHasNamedTeam(string teamName)
{
// do some logic here and return
// TestCaseResult
}
...
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
// I want to get the value of the TestDescription attribute here
}
...
// usage
TestThat(() => TargetHasOneTeam());
TestThat(() => TargetHasNamedTeam("Adapter5"));
As you can see from the example, I'd really like to be able to get the TestDescriptionAttribute attribute from within the TestThat() function. I've already poked through the Action parameter which contains my method but haven't been able to "find" my TargetHasOneTeam() method.

If you change TestThat(() => TargetHasOneTeam()) (you wrapping your delegate into another action) to TestThat(TargetHasOneTeam) and change TestThat like this:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
var attrs = action.GetInvocationList()[0].Method.GetCustomAttributes(true);
// I want to get the value of the TestDescription attribute here
}
will give you what you need.
With expressions:
public static void TestThat(Expression<Func<TestResult>> action)
{
var attrs = ((MethodCallExpression)action.Body).Method.GetCustomAttributes(true);
var result = action.Compile()();
}

In this particular case it's essentially inaccessible. You are creating a lambda which executes the method in question. That lambda eventually results in a new method being generated which is eventually the argument of the Action delegate. That method has no relation to TargetHasOneTeam and is only apparently if you dig through the IL instructions in the body.
You could skip the lambda and do a method group conversion here.
TestThat(TargetHasOneTeam);
Now TargetHasOneTeam is being directly assigned to the delegate instance and would be visible in the Delegate::MethodInfo property.
Note: In general though this is a bad idea for precisely the problem you're encountering. The attributes on the method shouldn't affect it's ability to satisfy the delegate instantiation. I would avoid this type of inspection if possible.

You can get the attribute of any member with Attribute.GetCustomAttribute. First check that the attribute is defined. For example:
public static void TestThat(TestCaseBase.Action action)
{
TestCaseResult result = action.Invoke();
if(System.Attribute.IsDefined(action.Method, typeof(TestDescriptionAttribute)))
{
var attribute = (TestDescriptionAttribute)System.Attribute.GetCustomAttribute(action.Method,
typeof(TestDescriptionAttribute));
Console.WriteLine(attribute.TestDescription);
}
}

See this example on MSDN.
class TestAuthorAttribute
{
static void Test()
{
PrintAuthorInfo(typeof(FirstClass));
PrintAuthorInfo(typeof(SecondClass));
PrintAuthorInfo(typeof(ThirdClass));
}
private static void PrintAuthorInfo(System.Type t)
{
System.Console.WriteLine("Author information for {0}", t);
// Using reflection.
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // Reflection.
// Displaying output.
foreach (System.Attribute attr in attrs)
{
if (attr is Author)
{
Author a = (Author)attr;
System.Console.WriteLine(" {0}, version {1:f}", a.GetName(), a.version);
}
}
}

Related

How to search for a method in C# by attribute?

I'm writing a command line utility in C# for .NET Core. I want to allow the user to specify the "action" to run based on a command line parameter. I'm mimicking the PowerShell style command line options, so one of my options is /Action. So for example, the user might call the app with /Action:Update or /Action:Reset.
In C#, I have a method for each action that follows a specific method signature. So, for the Update method above, I have a method like this: public static int Update(Dictionary<string,string> cmdLineArgs, SomeObject obj). Each method that is related to a valid parameter on /Action has exactly the same signature (same types and variable names).
Right now I just have a switch block to call the actions, but this seems incredibly inefficient:
int returnValue;
switch (parsedArgs["action"]) {
case "update":
returnValue = Update(parsedArgs, o);
break;
case "reset":
returnValue = Reset(parsedArgs, o);
break;
...
default:
returnValue=255;
Console.WriteLine($"No such action {parsedArgs["action"]}.");
break;
}
I've used attributes in the context of Web APIs, and they seem to be a natural starting point to make this more generic. This would ideally result in the situation where adding a new action is as simple as writing its method and adding the correct attribute with the name the user can call it by in the /Action switch. My idea is to create a custom attribute (say, AppActionName) and then put that attribute on any method that can be called as an action from the command prompt:
[AppActionName("update")]
public static int Update(Dictionary<string,string> cmdLineArgs, SomeObject obj)
...
[AppActionName("reset")]
public static int Reset(Dictionary<string,string> cmdLineArgs, SomeObject obj)
...
An alternative I've thought about, which would take advantage of type safety, would be to use an interface that defines the action method:
public interface IAppAction
{
int Run(Dictionary<string,string> cmdLineArgs, SomeObject obj);
}
[AppActionName("update")]
public class UpdateAction : IAppAction
{
public int Run(Dictionary<string,string> cmdLineArgs, SomeObject obj)
...
[AppActionName("reset")]
public class ResetAction : IAppAction
{
public int Run(Dictionary<string,string> cmdLineArgs, SomeObject obj)
...
In either case though, what I'm not sure of is how to actually search for, instantiate and run the method.
In the first option (putting the AppActionName directly on the method), I see two problems: 1) having to figure out how to search all methods in the assembly for those with the given attribute, filtering, and then how to actually call the method, and 2) unless I don't know how to do it, I don't think I can enforce the proper method signature using this method.
int returnValue;
// in other languages you can get a variable and then call it, but this isn't other languages
// but you might do something like: myMethod = findMethodWithAttribute("update"); returnValue=myMethod(parsedArgs, o);
The second option (interface on class implementing interface) seems more type-safe and should be easier to implement (declare an interface-variable and then have it assigned to an instance of the correct class), but I'm still not sure how to actually search for the attribute with the correct name.
int returnValue;
// how would you do this correctly?
IAppAction appActionClass = new FindTheClassWithTheAttributeWithParameter("update")();
returnValue = appActionClass.Run(parsedArgs, o);
So i think the essence of my question is: "how do I find which method/class has the attribute I defined with the parameter I specified, and then how do I actually instantiate/call the result?"
The second approach should generally be easier to deal with.
I made an example (which you can run here) for getting the classes that implement the interface and their attribute.
Given something like this:
public class AppActionNameAttribute : Attribute
{
public string Action { get; set; }
public AppActionNameAttribute(string action) { Action = action; }
}
public interface IAppAction
{
int Run(Dictionary<string,string> cmdLineArgs, SomeObject obj);
}
[AppActionName("update")]
public class UpdateAction : IAppAction
{
public int Run(Dictionary<string,string> cmdLineArgs, SomeObject obj)
{
Console.WriteLine("Handled :)");
return 1;
}
}
public class SomeObject { }
You can do this:
var handlers = typeof(Program).Assembly
// Get all types in the assembly
.GetExportedTypes()
// that are classes and implement IAppAction
.Where(x => x.IsClass && x.GetInterface("IAppAction") != null)
.Select(x => new
{
// assuming they are always decorated with [AppActionName]
Action = x.GetCustomAttribute<AppActionNameAttribute>().Action,
// get a new instance, assuming parameterless constructor
Handler = (IAppAction)Activator.CreateInstance(x)
})
// and convert it to a Dictionary that you can easily use
.ToDictionary(x => x.Action, x => x.Handler);
Which you can store (preferably in some static field as you don't want to be running this often) and simply use like this:
private static Dictionary<string, IAppAction> _handlers = ...;
public static void Main()
{
string action = Console.ReadLine();
// you should check the action actually exists in the Dictionary
var handler = _handlers[action];
// and then run it:
Console.WriteLine(handler.Run(someData, otherData));
}

C# Creating a basic event manager using Action, passing optional params to Invoke

I'm trying to create a simple event manager, but I'm struggling to create it the way I want.
Here is what I have so far, and it works. However, I can not figure out how I can allow for different parameters and them being optional.
using System.Collections.Generic;
using System;
public static class Event_Manager {
public static Dictionary<string, Action> event_list = new Dictionary<string, Action>(){
{
"enemy_killed", null
},
{
"enemy_spawned", null
}
};
public static void on(string evt, Action act){
Action item;
if(event_list.TryGetValue(evt, out item)){
event_list[evt] += act;
}
}
public static void off(string evt, Action act){
Action item;
if(event_list.TryGetValue(evt, out item)){
event_list[evt] -= act;
}
}
public static void trigger(string evt){
Action item;
if(event_list.TryGetValue(evt, out item)){
item.Invoke();
}
}
}
Example of using it:
public void some_method(){
// Do something when an enemy has been killed;
}
Event_Manager.on("enemy_killed", some_method);
Event_Manager.trigger("enemy_killed");
What I would like is to be able to do is pass different types of parameters as well (or some sort of object that could be an event that the methods receive).
public void player_damaged(int damage){
// Reduce health
}
Event_Manager.on("player_hit", player_damaged);
Event_Manager.trigger("player_hit", 15);
Any help would be much appreciated.
Thanks
As you surely have noticed the delegate type Action has no parameters. Keep that in mind.
One solution is to pass an object with the extra parameters. The detail with this is that you don't know the types or even the quantity of the parameters you need.
In .NET this was solved by having EventArgs, and for each new event that needs
a different combination of extra parameters a derived type is created.
That means you would use it like:
Event_Manager.trigger("player_hit", new PlayerHitEventArgs(15));
Where PlayerHitEventArgs is a class that inherits from EventArgs, and the trigger method takes an EventArgs. Similary, you would be using Action<EventArgs> (both in parameters and in the internal dictionary).
For what I get, you want to avoid the hassle.
The next option is to always pass an object, then the recieving party will have to check the type and try to cast it. Or better yet, pass dynamic.
In that case you would be using Action<dynamic>, the trigger method would take dynamic, and now you can pass anonymous types:
public void player_damaged(dynamic data){
var damage = data.damage;
// Reduce health
}
Event_Manager.on("player_hit", player_damaged);
Event_Manager.trigger("player_hit", new {damage = 15});
Note: also change the type of the dictionary accordingly.
If you want the code to be able to detect how many parameters does the act method have, and try to pass the parameters accordingly you will need a bit of reflection.
First you will have to relax the type from Action to simply Delegate because you will be passing things that take all amounts of parameters.
Then, in order to invoke, you first need to read what parameters does the current delegate have. To do that, you will have to get the MethodInfo of the delegate:
MethodInfo methodInfo = item.Method;
And you also need the target object of the delegate, because it may not be an static method:
object target = item.Target;
Now, we can read the parameter list frm the MethodInfo:
var paramList = method.GetParameters();
We have to build an array to invoke the method, the size we get from the list:
var args = new object[paramList.Length];
And start populating it with the values from the object. There is no need to use dynamic here.
Code for trigger:
public static void trigger(string evt, object obj){
Delegate item;
if(event_list.TryGetValue(evt, out item)){
// Get MethodInfo and Target
MethodInfo methodInfo = item.Method;
object target = item.Target;
// Get the parameter list
var paramList = methodInfo.GetParameters();
// Get the type of the obj
var type = obj.GetType();
// Build the argument list
var args = new object[paramList.Length];
for (int index = 0; index < paramList.Length; index++)
{
var parameter = paramList[index];
var name = parameter.Name;
// Get the value from obj
var property = type.GetProperty(name);
var value = property.GetValue(obj, null);
args[index] = value;
}
// Invoke
methodInfo.Invoke(target, args);
}
}
Note: no exception handling. Also remember to undate the dictionary that holds the delegates.
Example usage:
public void player_damaged(int damage){
// Reduce health
}
Event_Manager.on("player_hit", new Action<int>(player_damaged));
Event_Manager.trigger("player_hit", new {damage = 15});
The property damage passed in trigger is mapped to the parameter damage in player_damage by name. I tested this works.
Note: Since on would be taking Delegate the compiler can't choose a delegate type for the "method group", so the cast to a delegate type is needed.
Then you need to change your dictionary into
Dictionary<string, Action<object>>
and trigger method would be like
public static void trigger(string evt, object parameter){
Action<object> item;
if(event_list.TryGetValue(evt, out item)){
if (item != null) {
item.Invoke(parameter);
}
}
}
But in this case you lose all beauty of strongly typed approach, and you will need to do unboxing from the object.

How can I pass several methods (with parameters) AS a parameter?

Suppose I have the following WCF code:
try
{
ServiceClient proxy = new ServiceClient();
proxy.ClientCredentials.UserName.UserName = "user";
proxy.ClientCredentials.UserName.Password = "password";
proxy.GetData(2);
if (proxy.State = CommunicationState.Opened)
{
proxy.GetData("data");
}
proxy.Close();
}
catch (FaultException ex)
{
// handle the exception
}
And since I notice that the try...catch and other logic is repetitive, not to mention that setting up a WCF call is expensive, I want to send many "methods and parameters" to this function.
In essence pass GetData(2) and GetData("data") as a method array, and have the results return either asynchronously or synchronously.
How would I accomplish this?
I suppose I could have two 'ref' objects to handle the results[] and a shared lock to the results[]. However I'm not sure how to pass "methods with parameters" as a parameter to another function.
Perhaps another way of looking at this might be an array of function pointers, to the same function with different params.
Can anyone nudge me into the right way of doing this?
More info:
I am asking this question so I can optimize this approach to handling WCF exceptions and retries but so I don't have to always open/close the client after each call.
Use delegates and pass them in a list.
The C# Func<T> delegate is used when a return value is needed.
List<Func<Data>> funcList = new List<Func<Data>>();
funcList.Add( () => GetData(2) );
// You can use any condition as you otherwise would to add to the list.
if (proxy.State = CommunicationState.Opened)
{
funcList.Add( () => GetData("data") );
}
List<Data> ProcessFuncs(List<Func<Data>> funcDatas)
{
List<Data> returnList = new List<Data>();
foreach(var func in funcDatas)
{
returnList.Add(func());
}
}
( as long as the return types are identical, this will work )
This is just an example of course; if your methods don't return anything, you can use the C# Action delegate, which just executes an action and doesn't return any value.
List<Action> actionList = new List<Action>();
actionList.Add( () => ProcessData("data")); // ProcessData is a void with no return type
actionList.Add( () => ProcessData(2));
public void ProcessActions(List<Action> actions)
{
foreach(var action in actions)
{
action();
}
}
In response to some comments:
This code compiles and is all equivalent:
class Program
{
public static string GetData(string item) { return item; }
public static string GetData(int item) { return item.ToString(); }
static void Main(string[] args)
{
string someLocalVar = "what is it?";
int someLocalValueType = 3;
Func<string> test = () =>
{
return GetData(someLocalVar);
};
Func<string> test2 = () => GetData(someLocalValueType);
someLocalValueType = 5;
List<Func<string>> testList = new List<Func<string>>();
testList.Add(() => GetData(someLocalVar));
testList.Add(() => GetData(2));
testList.Add(test);
testList.Add(test2);
someLocalVar = "something else";
foreach(var func in testList)
{
Console.WriteLine(func());
}
Console.ReadKey();
}
}
Result is:
I wouldn't use delegates here because then you are constrained by types and to solve that it becomes horrible and over-complicated. I would just have a callback that gives you free reign over the ServiceClient once it has been set up. I think this is a pattern that has a name but I don't know.
interface IProxyActionCallback
{
void DoProxyStuff(ServiceClient proxy);
}
void MyMethod(IProxyActionCallback callback)
{
try
{
ServiceClient proxy = new ServiceClient();
proxy.ClientCredentials.UserName.UserName = "user";
proxy.ClientCredentials.UserName.Password = "password";
callback.DoProxyStuff(proxy);
proxy.Close();
}
catch (FaultException ex)
{
// handle the exception
}
}
Then you call the method like:
MyMethod(new DoSpecificStuff());
Where DoSpecificStuff is a class that implements the interface and allows you to do specific calls with the proxy:
class DoSpecificStuff : IProxyActionCallback
{
public void DoProxyStuff(ServiceClient proxy)
{
proxy.GetData(2);
if (proxy.State = CommunicationState.Opened)
{
proxy.GetData("data");
}
}
}
So you'd have tons of classes that implement the interface, and they all "share" the same try-catch boiler-plate proxy stuff which is in one place.
Bellow is an example of how to make a collection of delegates and their arguments then invoke them later on without knowing the methods definition. As far as I know if you want to invoke methods with different definitions in a single general call you have to do something like this.
List<Tuple<delegate, object[]>> delegates = new List<Tuple<delegate, object[]>>();
delegates.Add(new Tuple<delegate, object[]>(new Func<Arg1Type, Arg2Type, ReturnType>(MyFunctionName), new object[] { arg1, arg2 });
foreach (Tuple<delegate, object[]> d in delegates)
{
d.Item1.DynamicInvoke(d.Item2);
}
You could use C# delegates:
A delegate is a type that represents references to methods with a
particular parameter list and return type. When you instantiate a
delegate, you can associate its instance with any method with a
compatible signature and return type. You can invoke (or call) the
method through the delegate instance. Delegates are used to pass
methods as arguments to other methods. Event handlers are nothing more
than methods that are invoked through delegates. You create a custom
method, and a class such as a windows control can call your method
when a certain event occurs. The following example shows a delegate
declaration:
More on this:
http://msdn.microsoft.com/en-us/library/ms173171.aspx
You can pass functions with parameters this way:
public void strategy<R, T1, T2>(Func<R, T1, T2> f);
public bool predicate(string a, string b);
strategy<bool, string, string>(predicate);
The first line declares the function strategy() accepting a function f;
That function return the type R and takes two parameters of type T1 and T2.
The second line defines a function that returns a bool and accepts two string.
The third line invokes the strategy passing it the predicate as a parameter.
Not sure to understand what you're trying to achieve, but basically if your service exposes a GetData(int) method and a GetData(string) method as well as an async proxy, you should call both asynchronously using something like:
var getData = proxy.GetDataAsync(2);
var getData2 = proxy.GetDataAsync("data");
await Task.WhenAll(getData, getData2);
// Gets the result using getData.Result...etc.

Creating a genericly typed Action<> at runtime

Is it possible to create a generically typed Action at run time based on some specified types? In this particular scenario, the body of the Action will ultimately ignore the argument types, as the typed Action<> will just be a wrapper around a no-argument Action, e.g.
Action original = () => { };
...
Action<TType> wrapper = (arg) => {
original();
}
Or, even:
Action<TTypeA, TTypeB> wrapper = (arg) => {
original();
}
As you can see, the body of the typed Action<> ignores the arguments, and their type, it's just acting as a wrapper.
If you're curious as to why I want create this wrapper in the first place, the 'basic' version is that I am ultimately converting the Action to a Delegate for doing a Delegate.Combine(), which requires identical types. All I am trying to accomplish with the Delegate.Combine() is a basic notification that the delegate was fired.
At this point I will probably re-work my design to avoid these types of shenanigans, but I am still very curious how this might be accomplished.
The closest I could get was the following:
private static TType GetTypedDelegate<TType>(Action onComplete)
where TType : class
{
MethodInfo info = typeof(TType).GetMethod("Invoke");
ParameterInfo[] parameters = info.GetParameters();
object result;
if (parameters.Length == 0)
result = onComplete;
else if (parameters.Length == 1)
result = GetTypedDelegate<TType>(onComplete, parameters[0].ParameterType);
// etc
TType onCompleteCasted = Delegate.CreateDelegate(typeof(TType), result, "Invoke") as TType;
return onCompleteCasted;
}
private static Delegate GetTypedDelegate<TType>(Action onComplete, Type type)
{
// This line isn't useful for me right now, since I can't just create a new
// instance of the action with a parameterless constructor ... but I thought I'd throw it in here in case it was of use
Type actionType = typeof(Action<>).MakeGenericType(new[] { type });
// Do some magic here with the type information
// The following of course does not work,but you get the idea of what I am aiming for
Action<type> wrapper = (arg1) =>
{
onComplete();
};
return wrapper as Delegate;
}
I think that the easiest option is to write a generic method and then invoke it dynamically (using Reflection or possibly even using C# 4 dynamic):
class Helper {
public static Action<TType> Wrap1<TType>(Action arg) {
return (arg) => { original(); }
}
}
Invoking the method using Reflection and using typ1 as the generic type argument could look like this:
var meth = typeof(Helper).GetMethod("Wrap1");
var gmeth = meth.MakeGenericMethod(new[] { typ1 });
var genericAction = gmeth.Invoke(null, new object[] { action });
If you don't want to use reflection you can setup some classes like this.
public class ActionWrapper<TTypeA>
{
protected readonly Action _original;
public ActionWrapper(Action original)
{
_original = original;
}
public Action<TTypeA> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a)
{
_original();
}
}
public class ActionWrapper<TTypeA,TTypeB>:ActionWrapper<TTypeA>
{
public ActionWrapper(Action original) : base(original)
{
}
public new Action<TTypeA, TTypeB> Wrapped { get { return WrappedAction; } }
private void WrappedAction(TTypeA a,TTypeB b)
{
_original();
}
}

How do I get the custom attributes of a method from Action<T>?

How can I get the custom attributes of a method from a Action<T> delegate?
Example:
//simple custom attribute
public class StatusAttribute : Attribute
{
public string Message { get; set; } = string.Empty;
}
// 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 realize I could do this by using reflection on Foo, but for what I'm trying to create I have to use an Action<T>.
The problem is that the action doesn't directly point at Foo.DoSomething. It points at a compiler-generated method of the form:
private static void <>__a(Foo m)
{
m.DoSomething();
}
One option here would be to change it to an Expression<Action<T>>, then you can dissect the expression tree afterwards 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 issue is that the lambda m => m.DoSomething() is not the same as DoSomething. It is a lambda expression which gets compiled into a method call on a compiler-generated method, possibly using a compiler-generated type (though maybe not the latter, since there are no captured local variables).
A very verbose way of getting an Action<Foo> from an instance (non-static) method of the Foo type is this:
var myAction = (Action<Foo>)Delegate.CreateDelegate(
typeof(Action<Foo>),
null, // treat method as static, even though it's not
typeof(Foo).GetMethod("DoSomething", BindingFlags.Instance | BindingFlags.Public)
);
Obviously, that is far from ideal and probably in fact useless in your case; but it's worth knowing ;)
Update: Actually, it just occurred to me you could write a quick extension method to make this easy for any instance method that you want to wrap as a static method (and maintain 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 would allow you to do:
Action<Foo> myAction = new Action(new Foo().DoSomething).ToStaticMethod<Foo>();
Admittedly, it's not as nice as m => m.DoSomething(); but it does give you an Action<T> whose Method property actually references the DoSomething method directly.
Alternately, instead of an Action<T>, you could use an Expression<Action<T>> and get the MethodInfo from that. Note that the syntax looks just the same in this case:
Action<Foo> myAction = m => m.DoSomething();
Expression<Action<Foo>> myExpression = m => m.DoSomething();
But that is a tricky proposition since an arbitrary Expression<Action<T>> is not guaranteed to be as simple as just m => m.DoSomething().
None of previous answers (except #Marc Gravell♦ 's which has no user's code) seems to be compilable :)
So I would propose mine:
private static void CallDoSomething()
{
var f = new Foo();
Action myAction = f.DoSomething;
IEnumerable<StatusAttribute> statusAttributes = myAction.Method.GetCustomAttributes<StatusAttribute>(true);
}

Categories

Resources