Search code examples
c#genericsreflectionstatic-methods

Get static method with generic using reflection


I have several extension methods with same name and different receiving argument:

public static List<T>? MapTo<T>(this List<ClassA_DataModel> data) where T : ClassA_BusinessModel, new() { ... }
public static List<T>? MapTo<T>(this List<ClassB_DataModel> data) where T : ClassB_BusinessModel, new() { ... }
... (+50)

used to mapp (1:1) between different DataModels to their corresponding BusinessModels (EDIT1), and need to use reflection to invoke the right method according to the List<MyClassX_DataModel> passed as parameter:

var businessObjects = (typeof(MapperModel)?.GetMethod(nameof(MapperModel.MapTo))?.MakeGenericMethod(businessModelType).Invoke(null, new[] { dataObjects }) as IList)?.Cast<object>().ToList();

The problem is that I get an Exception because there are more than one method with the same name:

System.Reflection.AmbiguousMatchException: 'Ambiguous match found'

My guess would be to do something like this:

var myMethod = typeof(MapperModel)?.GetMethods().FirstOrDefault(m => m.Name == nameof(MapperModel.MapTo) && m.XXXX == businessModelType);
var businessObjects = (myMethod.MakeGenericMethod(businessModelType).Invoke(null, new[] { dataObjects }) as IList)?.Cast<object>().ToList();

but I don't know how to get the comparision part to work, provided that I have to match a List<BusinessModel>.

EDIT

I have to use generics for the methods, instead of just declaring my methods like this (without the use of generics):

public static List< ClassA_BusinessModel>? MapTo(this List<ClassA_DataModel> data) { ... }

because I will later be also invoking on a Dictionary where a lot of different data models will be listed:

public static List<T>? MapTo<T>(this Dictionary<Type, IList> dataset) where T : Class36_BusinessModel, new() { ... }

This way I will manage providing a mapping from different DataModels to one BusinessModel (n:1):

List<Class17_DataModel> data17 = (...)
List<Class23_DataModel> data23 = (...)
(...)
var dataset = new Dictionary<Type, IList>()
{
   [Class17_DataModel] = data17,
   [Class23_DataModel] = data23,
   (...)
}
var business17 = data.MapTo<Class17_BusinessModel>();
var business36 = dataset.MapTo<Class36_BusinessModel>();

Any suggestion?

Thanks in advance!


Solution

  • I found a workaround to solve my question. First I get all methods matching my given name

    var methods= (typeof(MapperModel)?.GetMethods().Where(x => x.Name == nameof(MapperModel.MapTo);
    

    and then I try-catch invoking every method with the types and parameters I am interested in in each case:

    var listType = typeof(List<>).MakeGenericType();
    var dictType = typeof(Dictionary<,>).MakeGenericType(Type, IList);
    

    The try-catch will throw an exception for those methods on which I will try invoking types and/or parameters for which they are not intended for, but this suits for the moment as a workaround solution. I would anyway be happier with something like

    var myMethod= (typeof(MapperModel)?.GetMethods().Single(m => m.Name == nameof(MapperModel.MapTo) && m.XXXXXXX== listInst?.GetType());
    var myMethod= (typeof(MapperModel)?.GetMethods().Single(m => m.Name == nameof(MapperModel.MapTo) && m.XXXXXXX== dictInst?.GetType());