c#Correct Parameter Type for GetMethod

In the code below, how should I be setting the variable "paramType" so that it matches the method shown in the GetMethod() call?

The code below does NOT match the method in the sample class (methodInfo is null).

using System;
using System.Linq.Expressions;

public class MyClass<TClass>
{
    public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
    {
    }
}

class Program
{
    static void Main( string[] args )
    {
        var classType = typeof( MyClass<> );

        // What should this really be?
        var paramType = typeof( Expression<> ).MakeGenericType( typeof( Func<,> ) );

        var methodInfo = classType.GetMethod( "MyMethod", new Type[] { paramType } );
    }
}

EDIT: I know how to get the MethodInfo using GetMethods or some other form of iteration / assumption. My question is specifically about how to set the System.Type of paramType, if its even possible to generate a System.Type for it.

EDIT 2: To be more specific with the problem, I've updated the code with more flavor:

using System;
using System.Linq.Expressions;

public class MyClass<TClass>
{
    public void MyMethod<TMethod>( Expression<Func<TClass, TMethod>> expr )
    {
        Console.WriteLine( "Type: {0}   Return: {1}", typeof( TClass ).Name, typeof( TMethod ).Name );
    }

    public void MyMethod<TMethod>( TMethod param )
    {
    }
}

class Program
{
    public int MyProperty { get; set; }

    static void Main( string[] args )
    {
        var classType = typeof( MyClass<> );

        var typeClass = typeof( Program );
        var typeMethod = typeof( int );

        // What should this really be?
        var paramType = typeof( Expression<> )
                 .MakeGenericType( typeof( Func<,> )
                                   .MakeGenericType( typeClass, typeMethod )
                                 );

        var methodInfo = classType
                        .MakeGenericType( typeClass )
                        .GetMethod( "MyMethod", new Type[] { paramType } );
    }
}

This doesn't work either- this different version of paramType with more information doesn't seem to match.

In the non-general case, someone may want to call "MyMethod" like this:

// I want to use a MethodInfo to perform this function:
new MyClass<Program>().MyMethod( _program => _program.MyProperty );

I believe the answer to your question is, "There is no way to do this".

Since GetMethod is not able to "MakeGenericMethod" while its doing its lookup, you have a method with one generic parameter that's known (TClass) and one that's not (TMethod). Reflection can't look up a method when some, but not all, of the parameters are known.

Note- Even though you do know what TMethod is supposed to be ("int" in your example), this would require the "MakeGenericMethod" that I referenced in the previous paragraph.

To do this you need to know the generic types, I don't think your task would be possible otherwise.

If your intention was to create a generic methodinfo for a generic class, before it knows any of its types, so you can later call MakeGenericType with your two types on it, that won't possible.

This can be shown by calling typeof(MyClass<>).GetMethod("MyMethod"), which will return null.

If you know the specific types on the other hand, that's easy:

static MethodInfo GetMethod(Type classType, Type methodType)
{
    var genericClassType = typeof(MyClass<>).MakeGenericType(classType);
    var methodInfo = genericClassType.GetMethod("MyMethod");
    var genericMethodInfo = methodInfo.MakeGenericMethod(methodType);
    return genericMethodInfo;
}

Notice that I don't create a generic type for the Expression<Func<TClass,TMethod>> parameter.

When you create the genericClassType and call GetMethod on it, the CLR doesn't know yet, what type TMethod would be. This is only know as soon as you call MakeGenericType on methodInfo. Therefore if you would call GetMethod with a fully parametrized Expression<Func<TClass,TMethod>> type, it wouldn't find the method.

That's why you need to call genericClassType.GetMethod("MyMethod") without the parameter types and possibly have to filter it, if the method is overloaded. Afterwards you can call MakeGenericMethod(methodType) and have your fully parametrized methodInfo object.

Related Articles
  • When does the Scala compiler really need the type information of parameters of anonymous functions? For instance, given this function: def callOn[T,R](target: T, f: (T => R)) = f(target) then I cannot use it like this: callOn(4, _.toString) => error
  • This question already has an answer here: What is a correct mime type for docx, pptx etc? 2 answers I want excel files on a website to open in Excel when clicked, not get saved on desktop, or get opened embedded in a browser etc. Now obviously it all
  • This question already has an answer here: What is the correct JSON content type? 27 answers I am having problems converting the JSON string in Chrome. Thank you! The MIME media type for JSON text is application/json. Hope this helps
  • Good Afternoon Everyone, I am trying to dynamically invoke a function by passing its appropriate parameters. Let's say the function looks like this: public string CreatePerson(Person p) Object p is received as Json and I want to deserialize it into t
  • Possible Duplicate: The right JSON content type? i have problem on json it is only displaying " Content-Type: text/html" i am testing on localhost and my online code is header('Access-Control-Allow-Origin: *'); header('Content-Type: application/
  • Possible Duplicate: The *right* JSON content type? I am using Java for the server side programming, and I want to return JSON data from the server side. I have come across the several return formats of JSON as below application/json text/javascript t
  • I'm trying to set the content-type header for a JSON response accessed with an AJAX GET request. I've followed tutorials on blogs and the bakery but I always receive 'text/html' back from CakePHP. How do I set the content-type header correctly? Here'
  • I have a parser that parses into a boost::variant<int, double, std::string> namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; using namespace std; typedef map<string, boost::variant<int, double, string> > namevalu
  • I have two classes which both adhere to the same interface (IAccount). They each have a property called Preferences which adheres to another interface (IAccountPreference). I would like a way to generically create the preferences property (ie a metho
You Might Also Like