使用Lambda表达式获取方法名称

时间:2010-02-22 21:25:50

标签: c# reflection lambda

我正在尝试使用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

这种事情甚至可能吗?是否有其他方法可以在不使用魔术字符串的情况下完成此类操作?

4 个答案:

答案 0 :(得分:7)

有两种方法可以做到这一点:

1:你可以做出带有各种FuncAction代表的重载(例如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传递,而不强制任何返回类型。但它仍然有点混乱,因为你必须将一些参数传递给方法才能进行编译。