我正在尝试使用lambda表达式获取类型的方法名称。我正在使用Windows Identity Foundation,需要定义具有类型名称的访问策略,其中命名空间作为资源,方法名称作为操作。这是一个例子。
这是我将从以下类型获取类型名称和方法名称的类型:
namespace My.OrderEntry {
public class Order {
public void AddItem(string itemNumber, int quantity) {}
}
}
这就是我想通过DSL定义访问策略的方法:
ForResource<Order>().Performing(o => o.AddItem).AllowUsersHaving(new Claim());
从该声明中,我想将“My.OrderEntry.Order”作为资源,将“AddItem”作为动作。获取带有命名空间的类型名称是没有问题的,但我认为我不能将lambda用于我正在尝试的方法。
public static IPermissionExp Performing<T>(
this IActionExp<T> exp,
Func<T, delegate???> action) {} //this is where I don't know what to define
这种事情甚至可能吗?是否有其他方法可以在不使用魔术字符串的情况下完成此类操作?
答案 0 :(得分:7)
有两种方法可以做到这一点:
1:你可以做出带有各种Func
和Action
代表的重载(例如Expression<Func<T, Func<TParam1,TParam2, TReturn>>
。注意你的调用者需要在方法中明确指定泛型参数调用或创建委托。这将使用如下:
ForResource<Order>().Performing(o => new Action<string>(o.AddItem)).AllowUsersHaving(new Claim());
2:您可以使用包含方法调用的Expression<Action>
,并从表达式树中解析出正在调用的MethodInfo
。这可以这样使用:
ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim());
答案 1 :(得分:3)
如果您希望将动作委托方法的名称传入执行功能,看起来这就是您要查找的内容。
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
}
这将允许您调用这样的方法......
ForResource<Order>().Performing((o, a, b) => o.AddItem(a, b)).AllowUsersHaving(new Claim());
答案 2 :(得分:1)
我最近在工作中做了一件事,你使用lambda定义了一个方法,然后内部对象取名为。你也可以使用字符串,或传入一个MethodInfo,但第一个不是真正的类型安全(错别字是一个很大的风险),而后者不是很优雅。
基本上我有一个像这样的方法(这不是确切的方法,它有点高级):
public void SetRequest(Request req, Expression<Func<Service, Func<long, IEnumerable<Stuff>>> methodSelector);
这里的关键是“表达式”,这让你“选择”这样的方法:
SetRequest(req, service => service.SomeMethodTakingLongReturningStuffs);
将方法选择器制作成表达式树,然后可以从中获取不同的数据位。我不记得究竟是什么结果树,它还取决于你的lambda看起来如何。
答案 3 :(得分:0)
您可以将其作为Action传递,而不强制任何返回类型。但它仍然有点混乱,因为你必须将一些参数传递给方法才能进行编译。