I have this code:
MethodInfo method = typeof(AppDbContext)
.GetMethod(nameof(AppDbContext.Set), BindingFlags.Public | BindingFlags.Instance);
There are two methods named Set in DbContext
, Set<>()
and Set<>(string name)
the problem is, there is ambiguity with this code.
So how do I get the method with no parameters?
For such reflection manipulations, usually I'm using simple helper class, which extracts MethodInfo from LambdaExpression
.
Your code can be simplified via this helper in the following manner:
MethodInfo method = MemberHelper.MethodOfGeneric((AppDbContext ctx) => ctx.Set<object>());
And helper class implementation:
public static class MemberHelper
{
public static MethodInfo MethodOf<TResult>(Expression<Func<TResult>> methodCall) => GetMethodInfo(methodCall);
public static MethodInfo MethodOf<T1, TResult>(Expression<Func<T1, TResult>> methodCall) => GetMethodInfo(methodCall);
public static MethodInfo MethodOf<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> methodCall) => GetMethodInfo(methodCall);
public static MethodInfo MethodOf<T1, T2, T3, TResult>(Expression<Func<T1, T2, T3, TResult>> methodCall) => GetMethodInfo(methodCall);
public static MethodInfo MethodOfGeneric<TResult>(Expression<Func<TResult>> methodCall) => GetMethodInfo(methodCall).GetGenericMethodDefinition();
public static MethodInfo MethodOfGeneric<T1, TResult>(Expression<Func<T1, TResult>> methodCall) => GetMethodInfo(methodCall).GetGenericMethodDefinition();
public static MethodInfo MethodOfGeneric<T1, T2, TResult>(Expression<Func<T1, T2, TResult>> methodCall) => GetMethodInfo(methodCall).GetGenericMethodDefinition();
public static MethodInfo MethodOfGeneric<T1, T2, T3, TResult>(Expression<Func<T1, T2, T3, TResult>> methodCall) => GetMethodInfo(methodCall).GetGenericMethodDefinition();
static MethodInfo GetMethodInfo(LambdaExpression lambda)
{
if (GetMemberInfo(lambda) is not MethodInfo methodInfo)
throw new InvalidOperationException("Expression must be a method call expression.");
return methodInfo;
}
static MemberInfo GetMemberInfo(LambdaExpression func)
{
return GetMemberInfo(func.Body);
}
static MemberInfo GetMemberInfo(Expression expr)
{
if (expr is MemberExpression memberExpr)
return memberExpr.Member;
if (expr is MethodCallExpression methodExpr)
return methodExpr.Method;
throw new InvalidOperationException("Expression must be a member expression or a method call expression.");
}
}
It can be extended to get constructors, properties, etc.