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?
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());
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With