Search code examples
c#genericsreflectionextension-methods

How to call a generic static extension Method using Reflection?


Now before I start: I know that there are many questions like this already that have been answered.

I've tried the lot of them and they just don't seem to work for me and I'm not quite sure what I'm doing wrong. My running theory is that what the thing I'm trying to do is rather niche and also very "hey you shouldn't be doing it like this at all", and all the answers I've found have aged a good bit. But it has now really gotten my interest and I'm kinda locked in on finding out how to do it.

With all of this out of the way here is what I have:

public static class Extensions
{
    public static void AttemptToCallMethod<T>(DataTableFilter searchParameters, IEnumerable<T> aList)
    {
        IQueryable<T> queriedList = aList.AsQueryable();
        //this works
        Type sourceType = typeof(T);
        //this works
        Type columnType = typeof(T).GetProperty(searchParameters.ColumnProperty).PropertyType;   
        // the type in the specific instance is going to be int

        // this works
        Type searchParameterValueType = searchParameters.ColumnValue.GetType();  // this has a good chance of getting dropped since its always object but I want to keep my options open

        object[] parameters = new[] { searchParameters.ColumnValue, searchParameters.ColumnProperty };  // the parameters to be used later on

        // var typeOfContext = typeof(Queryable)  it's going to be one of the two I assume
        var typeOfContext = queriedList.GetType(); // this is the type I will use to get the method

        // something isn't right here
        var method = typeOfContext.GetMethod("GenericMethodTester"); // this is supposed to get me the Method but both the GetType() and typeof() deliver null

        // obviously throws an error since method is null for some reason
        var genericMethod = method.MakeGenericMethod(sourceType, searchParameterValueType, columnType);

        // never gets this far
        genericMethod.Invoke(queriedList, parameters);

        // here we have the smaller showcase Version to test around with and to proof that the Types/the amount of types aren't the problem
        var methodOne = typeOfContext.GetMethod("GenericMethodTesterOne");
        var genericMethodOneT = methodOne.MakeGenericMethod(sourceType);
        var genericMethodOneObj = methodOne.MakeGenericMethod(searchParameterValueType);
        var genericMethodOneCol = methodOne.MakeGenericMethod(columnType);
    }

    // this is a smaller version for the showcase, since the error message is the same and the error isn't really due to the parameters
    public static void GenericMethodTesterOne<TA>(this IQueryable<TA> tarra)
    {
    }

    public static void GenericMethodTester<TA, TB, TC>(this IQueryable<TA> typeA, TB typeB, TC typeC)
    {
        //the implementation of this is rather unimportant since the call is the problem
    }
}

The problem obviously is that for some reason the GetMethod never gives me any of my generics.

Now I'm not going to include the use case here since I do not think that it is relevant to the error, since the problem is that I can't find the method and that the methods aren't even listed when I use the GetMethods() on typeof() nor when I look at GetType().

My question is: what am I doing wrong here?

I've tried

This first

This second

This last

and some others in between

Now if you think I've left out some crucial information regarding your ability to reconstruct this you can tell me immediately.

The DataTableFilter class is just a string a object and a string, with property Column as a string and ColumnValue as object


Solution

  • Reflection doesn't work against instances for extension methods, because by definition it isn't the instance that defines it. Indeed, in theory there could be multiple GenericMethodTester extension methods in different namespaces, and only the using directives in the specific code file would resolve where the method is actually coming from. To get GenericMethodTester you must use typeof(Extensions).GetMethod(...), since it is Extensions that has the method, not the actual list/sequence/etc.