Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# reflection, get overloaded method

I've already checked a few other posts regarding reflection and overloaded methods but could find any help. One post I found was this one, but that didn't help a lot.

I have the following two methods:

1 | public void Delete<T>(T obj) where T : class { ... }
2 | public void Delete<T>(ICollection<T> obj) where T : class { ... }

I'm trying to get method N°1.

I tried the classic GetMethod("Delete") approach, but since there are two methods with this name a Ambiguous-Exception was thrown. I tried specifying the method schema with an additional parameter like GetMethod("Delete", new [] { typeof(Object) }) which didn't find anything (null returned).

I figgured I might as well just loop through all methods and check for the parameters.

I wrote the following method...

    public static IEnumerable<MethodInfo> GetMethods(this Type type, String name, Type schemaExclude)
    {
        IEnumerable<MethodInfo> m = type.GetRuntimeMethods().Where(x => x.Name.Equals(name));
        return (from r in m let p = r.GetParameters() where !p.Any(o => schemaExclude.IsAssignableFrom(o.ParameterType)) select r).ToList();
    }

... which returns the methods which do not contain a parameter with type schemaExclude.

I called it like this GetMethods("Delete", typeof(ICollection)) which didn't work as expected.

Apparently ..ICollection'1[T] is not assignable to ICollection. Neither is it to IEnumerable, IEnumerable<> and ICollection<>. I, again, tried it with typeof(Object) which did work but did return both methods (like its supposed to).

What exactly am I missing?

like image 684
Tobias Würth Avatar asked Oct 30 '22 06:10

Tobias Würth


1 Answers

You can look up the method by checking its generic parameter type, like this:

return type
    .GetRuntimeMethods()
    .Where(x => x.Name.Equals("Delete"))
    .Select(m => new {
         Method = m
    ,   Parameters = m.GetParameters()
    })
    .FirstOrDefault(p =>
        p.Parameters.Length == 1
    &&  p.Parameters[0].ParameterType.IsGenericType
    &&  p.Parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(ICollection<>)
    )?.Method;

The above filters methods that match the criteria below:

  • Called 'Delete',
  • With a single parameter,
  • With the parameter being a generic type,
  • With the generic parameter type constructed from ICollection<>

Demo.

like image 130
Sergey Kalinichenko Avatar answered Nov 12 '22 22:11

Sergey Kalinichenko