Scenario: I am trying to retrieve Custom Attributes from methods in a base class. The methods are async.
My base class implements virtual methods which contain default logic. Specifically, the class wraps an EF IRepository and exposes it as a Web API w/ Get/Post/Delete methods. Standard practice when subclassing this base is to add an attribute for Auth above the method override like [ResourceClaimsAuthorize(ResourceActions.Write, Resources.SomeResource)]. These attributes are what I'm trying to find.
Problems:
1) Because I'm in an async method, the AsyncStateMachine does it's thing and if I try to call MethodBase.GetCurrentMethod(), I will receive back "MoveNext()", rather than the actual method I'm in.
2) I've tried to use type.GetMethod(string methodName) instead. For this to work implicitly, I paired this approach with the [CallerMemberName] attribute which successfully grabs the method name. This partially worked - but broke the moment we encountered method overloads. It doesn't know how to determine which overload you want if overloads are present. This could be resolved by passing in an array of types to match the method signature of the overload we want - but I really don't want to muddy up our code by including an array of types into the logic - we're trying to reduce boiler plate and this feels like 1 step forward, 2 steps back.
3) I tried using a clever trick with Expression<Action<T>>
as a method selector. In this approach, my base class calls my Auth logic and passes in a lambda which "selects" the method I want. like:
apiController => apiController.Post()
Then you can grab the method off the MethodCallExpression pretty easily by simply grabbing
expression.Body.Method; // this will be the methodinfo of the method you selected in your lambda
This almost worked -- however the MethodCallExpression isn't selecting the method of the derived class, the expression's type is the base class for some reason, not the derived class as I expected. In my situation, this results in only finding custom attributes from the base class version of the selected method; it is still ignorant of the custom attributes on the derived, overridden version of that method; which is what I need.
Is there a better way? Ideally, I'd like to find my custom attributes just like I normally would, w/
var methodInfo = MethodBase.GetCurrentMethod();
var attributes = methodInfo.GetCustomAttributes<MyCustomAttribute>();
But the AyncStateMachine breaks that approach. Is there another way I can do that from inside an async method, that is just as easy? The GetCurrentMethod(string methodName) w/ [CallerMemberName] was almost a good fix if it weren't for the method overload naming collision, and the expression method selector approach almost worked if it weren't for it grabbing the base class method info instead of of the derived class method info.
Any ideas? Thanks for your time!