目前我的代码中有一个这样的方法:
.AddMethod(nameof(IRoleService.GetRoles))
我想要做的是使用lambda表达式选择接口方法,然后在AddMethod中获取方法的名称。 结果将是:
.AddMethod<IRoleService>(x=> x.GetRoles)
我试过这个:
AddMethod<T>(Expression<Func<T, Action>> expression);
但问题是一些接口方法有输入参数我试图忽略,因为我只需要方法名称。 如果你能帮助我,我将不胜感激。
亚历
答案 0 :(得分:3)
但问题是一些接口方法有输入参数 我试图忽略
除非这些参数具有默认值,否则您不能忽略输入参数。
如果您无法更改代码以将默认值设置为这些方法的输入参数,则需要使用反射自己提供默认值以获取所谓的输入参数并为其提供一些值。或者你可以在编译期间给它们:
// I don't know which parameters accept your methods...
AddMethod<IRoleService>(x => x.GetRoles("arg1", 2));
考虑到我只需要方法名称,你建议一个干净的方法 获取名称而不传递参数?
没有肮脏或干净的方式。表达式树仍然是有效的代码(即它应该是可以构建到可执行代码中的代码)。
如何生成表达式树,您可以在其中访问方法名称而不是调用它?或者如果整个方法都有参数,你如何访问一个方法来调用它而不用参数?这是有效的C#代码吗?答案是 否 。
答案 1 :(得分:0)
这可以通过一点点挖掘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 => x.GetRoles
语法直接调用,因为没有类型参数来定义x
是什么。这意味着您需要为AddMethod
和Action
支持的每个输入参数创建Func
的重载:
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