Currently in my code I have a method like this:
.AddMethod(nameof(IRoleService.GetRoles))
What Im trying to do is selecting the interface method using lambda expression and then get the name of method inside AddMethod. So the result would be :
.AddMethod<IRoleService>(x=> x.GetRoles)
I have tried this:
AddMethod<T>(Expression<Func<T, Action>> expression);
But the problem is some of the interface methods have input parameters which I'm trying to ignore, as I just need the method name. Would be thankful if you help me with this.
Alex
But the problem is some of the interface methods have input parameters which I'm trying to ignore
You can't ignore input parameters unless these parameters have default values.
If you can't change your code to set default values to these methods' input parameters, you'll need to provide default values yourself using reflection to get the so-called input parameters and give them some values. Or you can just give them during compile-time:
// I don't know which parameters accept your methods...
AddMethod<IRoleService>(x => x.GetRoles("arg1", 2));
considering I just need the Method Name, Do you suggest a clean way to get the name without passing parameters?
There's no dirty or clean way of doing so. Expression trees are still valid code (i.e. it should be code that can be built into executable code).
How you would produce an expression tree where you access a method name instead of calling it? Or how you access a method to call it without parameters if the whole method has parameters? Would be this valid C# code? The answer is no.
This can be achieved with a little bit of digging into the LambdaExpression
like this:
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;
}
Unfortunately GetMethodCallName
cannot be called directly with the x => x.GetRoles
syntax you want since there is no type argument to define what x
is. This means you'll need to create an overload of AddMethod
for every number of input arguments you want to support for both Action
and 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);
Then in each AddMethod
implementation call GetMethodCallName
with the expression argument:
void AddMethod<T, Arg1>(Expression<Func<T, Action<Arg1>>> expression)
{
var methodName = GetMethodCallName(expression);
}
Then you can call AddMethod
and specify the containing type and the return and input types of the method:
.AddMethod<IRoleService>(x => x.GetRoles);
.AddMethod<IRoleService, TResult>(x => x.GetRoles);
.AddMethod<IRoleService, Arg1, TResult>(x => x.GetRoles);
Where:
TResult
is the return type of .GetRoles
Arg1
is the type of the first argument of .GetRoles
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With