samedi 7 février 2015

How to perform method overload resolution for types known at runtime?

I have a class that contains method overloads :



public static void Foo(string a, string b)
public static void Foo(DateTime a, DateTime b)
public static void Foo<T>(ICollection<T> a, T b)
public static void Foo<T>(T a, ICollection<T> b)
public static void Foo<T>(ICollection<T> a, ICollection<T> b)
public static void Foo<T, U>(T a, U b) where T : IComparable
public static void Foo<T, U>(T a, U b)


I retrieve all methods at runtime this way :



var methods = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Static);


For two given parameter types (eg : typeof(int), typeof(List<int>)) I would like to dynamically select the most appropriate method.


What I tried/checked so far :



  • Binder.SelectMethod() : generics are not supported by that method.


  • typeof().IsAssignableFrom() : same as above. there is some support for generic parameters (eg : providing generic parameter T and its constraints against type int will be evaluated correctly) but not for generic type with arguments (eg : List<int> vs List<> or vs List<T> (this type would come from generic method and might T include some constraints))




  • calling MakeGenericMethod() with input parameters for all generic methods, and catching the argument exceptions until there is none : ugly. And it probably will need some additional work to be done because types I would provide to MakeGenericMethod() might not be exactly the same as initial types I receive (eg : I have typeof(List<int>), typeof(int) while i should provide typeof(int) to MakeGenericMethod().




I know this is a complex topic and no trivial problem but there is a few things that are fixed and should make things easier :



  • all methods have two parameters and the same return type

  • there is no optional types, no arrays.

  • generic methods have one or two generic parameters no more, with parameters always in same order.

  • covariance/contravariance does not need to be supported

  • methods are already sorted by "priority". that is why the generic one without constraints is at the end of this list. once one method has match we can take it and ignore the other methods


I would like to know if there is a way to do resolve these overloads using existing class/methods from C# Framework (without re-inventing the wheel) and if not possible what would be a possible solution (custom code)






Aucun commentaire:

Enregistrer un commentaire