【问题标题】:Selecting a class method name using Lambda Expression使用 Lambda 表达式选择类方法名称
【发布时间】:2016-03-29 05:25:57
【问题描述】:

目前在我的代码中,我有一个这样的方法:

.AddMethod(nameof(IRoleService.GetRoles))

我试图做的是使用 lambda 表达式选择接口方法,然后在 AddMethod 中获取方法的名称。 所以结果是:

.AddMethod<IRoleService>(x=> x.GetRoles)

我试过这个:

AddMethod<T>(Expression<Func<T, Action>> expression);

但问题是一些接口方法具有我试图忽略的输入参数,因为我只需要方法名称。 如果您能帮我解决这个问题,将不胜感激。

亚历克斯

【问题讨论】:

  • 新选择的答案如何解决您的问题?它可能适用于Action(无输入参数),但如果某些方法具有您在问题中所述的输入参数,会发生什么情况?

标签: c# linq reflection lambda


【解决方案1】:

但问题是一些接口方法有输入参数 我试图忽略它

您不能忽略输入参数,除非这些参数具有默认值。

如果您无法更改代码来为这些方法的输入参数设置默认值,您需要自己使用反射来提供默认值,以获取所谓的输入参数并给它们一些值。或者你可以在编译时给它们:

// I don't know which parameters accept your methods...
AddMethod<IRoleService>(x => x.GetRoles("arg1", 2));

OP 说...

考虑到我只需要方法名称,你有没有建议一种干净的方法来 不传参数获取名字?

这样做没有肮脏或干净的方式。表达式树仍然是有效代码(即它应该是可以构建到可执行代码中的代码)。

您将如何生成一个表达式树,您可以在其中访问方法名称而不是调用它?或者如果整个方法都有参数,你如何访问一个方法来调用它而不使用参数?这是有效的 C# 代码吗?答案是

【讨论】:

  • 感谢@Matías Fidemraizer。
  • 考虑到我只需要方法名称,您是否建议一种简洁的方法来获取名称而不传递参数?
  • 感谢您的详细描述。感谢您的帮助。
  • @Alex 不客气。好吧,有时答案是说您的问题没有解决方案... ;)
【解决方案2】:

这可以通过像这样深入LambdaExpression 来实现:

string GetMethodCallName(LambdaExpression expression)
{
    var unary = (UnaryExpression)expression.Body;
    var methodCall = (MethodCallExpression)unary.Operand;
    var constant = (ConstantExpression)methodCall.Object;
    var memberInfo = (MemberInfo)constant.Value;

    return memberInfo.Name;
}

不幸的是,GetMethodCallName 不能用你想要的 x =&gt; x.GetRoles 语法直接调用,因为没有类型参数来定义 x 是什么。这意味着您需要为ActionFunc 支持的每个输入参数数量创建AddMethod 的重载:

void AddMethod<T>(Expression<Func<T, Action>> expression);
void AddMethod<T, Arg1>(Expression<Func<T, Action<Arg1>>> expression);
void AddMethod<T, Arg1, Arg2>(Expression<Func<T, Action<Arg1, Arg2>>> expression);

void AddMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expression);
void AddMethod<T, Arg1, TResult>(Expression<Func<T, Func<Arg1, TResult>>> expression);
void AddMethod<T, Arg1, Arg2, TResult>(Expression<Func<T, Func<Arg1, Arg2, TResult>>> expression);

然后在每个AddMethod 实现中调用GetMethodCallName 并带有表达式参数:

void AddMethod<T, Arg1>(Expression<Func<T, Action<Arg1>>> expression)
{
    var methodName = GetMethodCallName(expression);
}

然后可以调用AddMethod,指定方法的包含类型和返回输入类型:

.AddMethod<IRoleService>(x => x.GetRoles);
.AddMethod<IRoleService, TResult>(x => x.GetRoles);
.AddMethod<IRoleService, Arg1, TResult>(x => x.GetRoles);

地点:

  • TResult.GetRoles 的返回类型
  • Arg1.GetRoles 的第一个参数的类型

【讨论】:

  • 这个答案如何解决问题? OP 说:但问题是某些接口方法具有我试图忽略的输入参数,因为我只需要方法名称。如果您能帮助我,将不胜感激。
  • 我更新了我的解决方案以适应输入参数。遗憾的是没有办法指定输入参数的类型,但至少不需要提供任何值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
相关资源
最近更新 更多