Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Method Name Using Lambda Expression

I'm trying to get the name of a method on a type using a lambda expression. I'm using Windows Identity Foundation and need to define access policies with the type name with namespace as a resource and the method name as the action. Here is an example.

This is the type I would be getting the type name and method name from:

namespace My.OrderEntry {
    public class Order {
        public void AddItem(string itemNumber, int quantity) {}
    }
}

This is how I would like to define the access policy through a DSL:

ForResource<Order>().Performing(o => o.AddItem).AllowUsersHaving(new Claim());

From that statement, I would like to get "My.OrderEntry.Order" as the resource and "AddItem" as the action. Getting the type name with namespace is no problem, but I don't think I can use a lambda for a method like I'm trying to do.

public static IPermissionExp Performing<T>(
    this IActionExp<T> exp,
    Func<T, delegate???> action) {} //this is where I don't know what to define

Is this sort of thing even possible to do? Is there another way to do this sort of thing without using magic strings?

like image 651
awilinsk Avatar asked Feb 22 '10 21:02

awilinsk


2 Answers

There are two ways to do this:

1: You could make overloads that take the various Func and Action delegates(eg Expression<Func<T, Func<TParam1,TParam2, TReturn>>. Note that your callers would need to specify the generic parameters explicitly, either in the method call or by creating the delegate. This would be used like this:

ForResource<Order>().Performing(o => new Action<string>(o.AddItem)).AllowUsersHaving(new Claim());

2: You could take an Expression<Action> that contains a method call, and parse out the MethodInfo being called from the expression tree. This would be used like this:

ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim());
like image 165
SLaks Avatar answered Sep 28 '22 08:09

SLaks


It looks like this is what you are looking for if you want the name of the action delegate method passed in to the Performing function.

public static IPermissionExp Performing<T>( 
    this IActionExp<T> exp, 
    Expression<Action<T, string, int>> action) 
{
    var expression = action.Body as MethodCallExpression;
    string actionMethodName = string.Empty;
    if (expression != null)
    {
        actionMethodName = expression.Method.Name;
    }
    // use actionMethodName ("AddItem" in the case below) here
}

This would allow you to call the method like this...

ForResource<Order>().Performing((o, a, b) => o.AddItem(a, b)).AllowUsersHaving(new Claim()); 
like image 22
Russell Giddings Avatar answered Sep 28 '22 07:09

Russell Giddings