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

发布于 2024-08-22 11:48:57 字数 788 浏览 6 评论 0 原文

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

这种事情到底有可能做到吗?有没有另一种方法可以在不使用魔法字符串的情况下完成这种事情?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

喜爱纠缠 2024-08-29 11:48:57

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

1:您可以进行重载,采用各种 FuncAction 委托(例如 Expression> 请注意,您的调用者需要在方法调用中或通过创建委托来显式指定通用参数。

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

2:您可以采用 < code>Expression 包含方法调用,并解析出从表达式树中调用的 MethodInfo 这将像这样使用:

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

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());
落花浅忆 2024-08-29 11:48:57

如果您希望将操作委托方法的名称传递给执行函数,那么这似乎就是您正在寻找的内容。

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()); 

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()); 
临风闻羌笛 2024-08-29 11:48:57

我最近在工作中做了一件事,您使用 lambda 定义了 a 方法,然后内部对象采用该方法的名称。您也可以使用字符串,或者传入 MethodInfo,但第一个并不是真正的类型安全(并且拼写错误是一个很大的风险),而后者也不是很优雅。

基本上我有一个这样的方法(这不是确切的方法,它更高级):

public void SetRequest(Request req, Expression<Func<Service, Func<long, IEnumerable<Stuff>>> methodSelector);

这里的关键是“表达式”的东西,这可以让你“选择”这样的方法:

SetRequest(req, service => service.SomeMethodTakingLongReturningStuffs);

方法选择器被制作成然后您可以从中获取不同的数据位的表达式树。我不记得生成的树到底是什么样子,它还取决于你的 lambda 表达式的样子。

I recently did a thing at work where you defined the a method using a lambda, which the internal object then took the name of. You could use strings as well, or pass in a MethodInfo but the first one isn't really type safe (and typos are a big risk), and the latter is not very elegant.

Basically I had a method like this (this is not the exact method, it is a bit more advanced):

public void SetRequest(Request req, Expression<Func<Service, Func<long, IEnumerable<Stuff>>> methodSelector);

The key here is the "Expression" thing, this lets you "select" a method like this:

SetRequest(req, service => service.SomeMethodTakingLongReturningStuffs);

Method selector is made into a expression tree which you can then fetch different bits of data from. I don't recall exactly what the resulting tree looks like, it also depends on how your lambdas look.

人生戏 2024-08-29 11:48:57

您可以将其作为操作传入,这不会强制任何返回类型。但它仍然有点混乱,因为您必须向该方法传递一些参数才能使其编译。

You could pass it in as a Action instead, which doesn't force any return type. It is still a little messy though, because you have to pass some arguments to the method in order for it to compile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文