6

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?

5
  • 2
    When using reflection and asking for methods with parameters with specific types you are not asking for methods with compatible types, you're asking for methods with parameters with those specific types. Any inheritance and interface-implementation that you want to support in this regard has to be handled by your code. So you asked for a "Delete" method that took a ICollection parameter, and there were none. Commented Jun 15, 2017 at 13:38
  • @LasseV.Karlsen Thanks for your comment. Yes that's what i figgured. That is why i followed a different approach in the method I wrote where I try to check if the type, which should be excluded, is assigned from the parameter type. This should cover any inheritance of classes. What do you suggest to check for? Any suggestion for a different approach? Commented Jun 15, 2017 at 13:40
  • 1
    Do you know T at compile-time? Then it´s simply GetMethods("Delete", typeof(ICollection<int>)) for example. Otherwise you´d have to build the runtime-type in front using Type.MakeGenericType. Commented Jun 15, 2017 at 13:46
  • @HimBromBeere at compile time? no. I use it in a very generic approach for data manipulation based on the entity framework. T could be any of the supported models of my domain. The object I'm handling is a proxy object which means I'm forced to use reflection to access the method with the proper generic type. I could try building the generic type at runtime to get ICollection<T>, but I'm not certain that this will match with the schema of the method. Let me try ... Commented Jun 15, 2017 at 13:49
  • @HimBromBeere I tried it with typeof(ICollection<>).MakeGenericType(t) where t equals the entity framework model type. My method returned both methods as a result which means that it didn't match the schema. Commented Jun 15, 2017 at 13:53

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer! That did indeed solve my problem, although the only thing i really needed from your demo was the ParameterType.IsGenericType part. I changed my check to schemaExclude.IsAssignableFrom(o.ParameterType.IsGenericType ? o.ParameterType.GetGenericTypeDefinition() : o.ParameterType) . That did the trick

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.