C# 使用Lambda表达式获取方法名

C# 使用Lambda表达式获取方法名,c#,reflection,lambda,C#,Reflection,Lambda,我正在尝试使用lambda表达式获取类型上的方法名。我使用Windows身份基础,需要定义以命名空间作为资源的类型名称和方法名称作为动作的访问策略。这里有一个例子 这是我将从中获取类型名和方法名的类型: namespace My.OrderEntry { public class Order { public void AddItem(string itemNumber, int quantity) {} } } 以下是我希望通过DSL定义访问策略的方式: Fo

我正在尝试使用lambda表达式获取类型上的方法名。我使用Windows身份基础,需要定义以命名空间作为资源的类型名称和方法名称作为动作的访问策略。这里有一个例子

这是我将从中获取类型名和方法名的类型:

namespace My.OrderEntry {
    public class Order {
        public void AddItem(string itemNumber, int quantity) {}
    }
}
以下是我希望通过DSL定义访问策略的方式:

ForResource<Order>().Performing(o => o.AddItem).AllowUsersHaving(new Claim());
ForResource()。正在执行(o=>o.AddItem)。AllowUserSwiding(新声明());
从该语句中,我希望获得“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
公共静态IPermissionExp正在执行(
这个IActionExp,
Func action){}//这就是我不知道该定义什么的地方

这样的事情有可能做到吗?有没有其他方法可以不使用魔法字符串来执行这类操作?

您可以将其作为动作传递,而不强制任何返回类型。不过还是有点混乱,因为您必须向该方法传递一些参数,以便对其进行编译。

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

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


方法选择器被制作成一个表达式树,您可以从中获取不同的数据位。我记不起结果树的确切外观,它还取决于lambda的外观。

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


1:您可以进行重载,以获取各种
Func
Action
委托(例如
Expression如果希望将Action委托方法的名称传递给执行函数,看起来这就是您要查找的

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
}
publicstaticipermissionexp正在执行(
这个IActionExp,
表达(行动)
{
var expression=action.Body作为MethodCallExpression;
string actionMethodName=string.Empty;
if(表达式!=null)
{
actionMethodName=expression.Method.Name;
}
//在此处使用actionMethodName(在下面的例子中为“AddItem”)
}
这将允许您像这样调用方法

ForResource<Order>().Performing((o, a, b) => o.AddItem(a, b)).AllowUsersHaving(new Claim()); 
ForResource()。正在执行((o,a,b)=>o.AddItem(a,b))。AllowUserShang(新索赔());

AddItem应该添加什么?AddItem做什么并不重要,我只需要不使用魔法字符串的方法名称。这有点重要。我认为你的标题是一个动作,但我不认为这是最好的答案。是否可以执行动作?我真的只需要获得方法名称来定义是否使用允许r对该类型(资源)调用该方法(操作).好的,我明白你现在要做的。还有一个问题-传递给AddItem的值将从何而来?操作会起作用,但我真的不关心参数。我可以这样做吗:Func,Func,FuncI必须知道方法签名。如果我有不同签名的方法,我必须使用di我遇到的每个签名都有不同的表达式。是的,您可以使用表达式或表达式来代替。我有置换(此IActionExp exp,Func操作)。这无法编译。我在前面的注释中不正确,无法使用表达式。但是表达式可以。如果您查看我的示例,则需要将要生成表达式树的委托的签名指定为表达式的类型参数。因此,您需要执行(此IActionExp,表达式操作)…SLaks答案充分显示了您将如何调用它。如果您不想指定方法的签名,我认为它不能比他的方式更“通用”和更漂亮。另一个“解决方案”这将是使用不同类型的参数指定大量执行重载,这些参数将覆盖广泛的可能方法签名。这在实现方面不是很明智,但它是一种替代方法。例如1)我可以使用“object”而不是“TParam1”吗?对于2)有没有不指定null参数的方法?+1。我想不出比你的第二个例子更一般的版本了。@Wili:1)不-委托不是协变的。2) 没有。没有我想要的那么干净,但我很确定我想要的是不可能的。第二个例子非常接近,我决定使用它。当然,这需要调用方知道并声明参数。很明显,如果你对其他答案有意见,那就不是你的#1偏好:-(
ForResource<Order>().Performing(o => new Action<string>(o.AddItem)).AllowUsersHaving(new Claim());
ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim());
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());