Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reflection: invoke a method with generic parameter

I everyone,

I have some issues with invoking a method with reflection.

The method sign is

public T Create<T, TK>(TK parent, T newItem, bool updateStatistics = true, bool silent = false)
        where T : class
        where TK : class;
    public T Create<T, TK>(TK parent, string newName, Language language = null, bool updateStatistics = true, bool silent = false)
        where T : class
        where TK : class;

I want to use the second overload.

My code is

typeof(ObjectType).GetMethod("Create")
            .MakeGenericMethod(new Type[] { typeof(Item), typeof(TKparent) })
            .Invoke(_objectInstance, new object[] { parent, name, _language, true, false });

where Item is a class, TKparent is a type variable and parent is a TKparent instance.

I get a System.Reflection.AmbiguousMatchException.

I think the problem is related to generics

I tried also this:

typeof(ObjectType).GetMethod("Create", new Type[] { typeof(TKparent), typeof(string), typeof(Globalization.Language), typeof(bool), typeof(bool) })
            .MakeGenericMethod(new Type[] { typeof(Item), typeof(Tparent) })
            .Invoke(_objectInstance, new object[] { parent, name, _language, true, false });

but in this case I get a System.NullReferenceException (no method found)

Can anyone help with this, I'm getting mad!

thank you

like image 442
Alex Avatar asked Oct 30 '22 04:10

Alex


1 Answers

The problem is that GetMethod finds multiple methods with that mane before you even tell it which overload you want. The overload of GetMethod that allows you to pass in an array of types works for non-generic methods, but since the parameters are generic you can't use it.

You need to call GetMethods and filter down to the one you want:

var methods = typeof(ObjectType).GetMethods();

var method = methods.Single(mi => mi.Name=="Create" && mi.GetParameters().Count()==5);

method.MakeGenericMethod(new Type[] { typeof(Item), typeof(TKparent) })
      .Invoke(_objectInstance, new object[] { parent, name, _language, true, false });

You could obviously inline all of that if you want, but it makes debugging easier if you separate it into separate lines.

like image 125
D Stanley Avatar answered Nov 15 '22 06:11

D Stanley