How to Invoke an Extension Method Using Reflection

How do I invoke an extension method using reflection?

As others said, extensions methods are compiler magic, you can alway use VS right click, go to definition to find the real type that implements the static method.

From there, it gets fairly hairy. Where is overloaded, so you need to find the actual definition that matches the signature you want. GetMethod has some limitations with generic types so you have to find the actual one using a search.

Once you find the method, you must make the MethodInfo specific using the MakeGenericMethod call.

Here is a full working sample:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace ConsoleApplication9 {
class Program {

class MyObject {
public string Name { get; set; }
}

public static void CallWhereMethod() {
List<MyObject> myObjects = new List<MyObject>() {
new MyObject { Name = "Jon Simpson" },
new MyObject { Name = "Jeff Atwood" }
};

Func<MyObject, bool> NameEquals = BuildEqFuncFor<MyObject>("Name", "Jon Simpson");

// The Where method lives on the Enumerable type in System.Linq
var whereMethods = typeof(System.Linq.Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(mi => mi.Name == "Where");

Console.WriteLine(whereMethods.Count());
// 2 (There are 2 methods that are called Where)

MethodInfo whereMethod = null;
foreach (var methodInfo in whereMethods) {
var paramType = methodInfo.GetParameters()[1].ParameterType;
if (paramType.GetGenericArguments().Count() == 2) {
// we are looking for Func<TSource, bool>, the other has 3
whereMethod = methodInfo;
}
}

// we need to specialize it
whereMethod = whereMethod.MakeGenericMethod(typeof(MyObject));

var ret = whereMethod.Invoke(myObjects, new object[] { myObjects, NameEquals }) as IEnumerable<MyObject>;

foreach (var item in ret) {
Console.WriteLine(item.Name);
}
// outputs "Jon Simpson"

}

public static Func<T, bool> BuildEqFuncFor<T>(string prop, object val) {
return t => t.GetType().InvokeMember(prop, BindingFlags.GetProperty,
null, t, null) == val;
}

static void Main(string[] args) {
CallWhereMethod();
Console.ReadKey();

}
}
}

How to use C# reflection to invoke an extension method with generic List parameter?

The type that you need to pass to MakeGenericMethod is string, not List<string>, because the parameter is used as T.

var mi = typeof(Extensions).GetMethod("List");
var stringGeneric = mi.MakeGenericMethod(typeof(string));
stringGeneric.Invoke(null, new object[] {new List<string> { "list of string"} });

Otherwise, you are making a method that accepts a list of lists of strings.

How to call a generic extension method with reflection?

The extension method isn't attached to the type Form, it's attached to the type MyClass, so grab it off that type:

MethodInfo methodInfo = typeof(MyClass).GetMethod("GenericExtension",
new[] { typeof(Form), typeof(string) });

Invoke Generic Extension method on an Object?

Keep in mind that extension methods are compiler tricks. If you look up the static method on the static class where the extension method is defined you can invoke it just fine.

Now, if all you have is an object and you are trying to find a particular extension method you could find the extension method in question by searching all your static classes in the app domain for methods that have the System.Runtime.CompilerServices.ExtensionAttribute and the particular method name and param sequence in question.

That approach will fail if two extension classes define an extension method with the same name and signature. It will also fail if the assembly is not loaded in the app domain.

The simple approach is this (assuming you are looking for a generic method):

static class Extensions {
public static T Echo<T>(this T obj) {
return obj;
}
}

class Program {

static void Main(string[] args) {

Console.WriteLine("hello".Echo());

var mi = typeof(Extensions).GetMethod("Echo");
var generic = mi.MakeGenericMethod(typeof(string));
Console.WriteLine(generic.Invoke(null, new object[] { "hello" }));

Console.ReadKey();
}
}

Extension method and reflection

Extension methods are just syntactic sugar to make your code look better. The only thing to remember is that they are actually static members of the static class, not methods on the type they are extending. Performance wise, invoking them through reflection is no different from invoking any other static method.

static class MyExtensions
{
public static void Foo(this int i)
{
// do something
}
}

var methodInfo = typeof(MyExtensions).GetMethod("Foo");
methodInfo.Invoke(null, new object[] { 1 });

Invoke extension method via reflection (Type.InvokeMember)

No. You have to find the static class declaring the extension method, and invoke the static method that way.

Extension methods are just syntactic sugar - there's the ExtensionAttribute applied to it, but that's all. The CLR really doesn't care about them, and code which calls them is exactly equivalent to calling the method via the declaring type.

In particular, which extension method is picked is partly determined by the namespaces which have been imported - which isn't a concept which is present in the reflection API to start with.

How to use reflection to get extension method on generic type

The problem is that extension methods don't modify the type they are 'extending'. What actually happens behind the scenes is that the compiler transparently translates all the calls that seem to be made on the object in question to calls to your static method.

ie.

int? input = new int?().TryParseNullable("12345");
// becomes...
int? input = YourClass.TryParseNullable(new int?(), "12345");

From there it becomes obvious why it's not showing up via reflection. This also explains why you have to have a using directive for the namespace where YourClass is defined for the extension methods to be visible to the compiler. As to how you can actually get at that information, I'm not sure there is a way, short of running over all the declared types (perhaps a filtered list of interesting classes, if you know that sort of information at compile time) looking for static methods with the ExtensionMethodAttribute ([ExtensionMethod]) defined on them, then trying to parse the MethodInfo for the parameter list to work out if they work on Nullable<>.

Getting generic overload by reflection for extension method in C#

You need to get the method that has generic arguments by calling GetGenericArguments(), as in this example Linqpad:

void Main()
{
var method = typeof(KeyValueConfigurationCollectionExtensions)
.GetMethods()
.Where(m => m.Name == "Get")
.Where(m => m.GetGenericArguments().Any())
.Single()
.Dump();

}

// Define other methods and classes here
public static class KeyValueConfigurationCollectionExtensions
{
public static string Get(this KeyValueConfigurationCollection collection, string key)
{
return collection[key].Value;
}
public static T Get<T>(this KeyValueConfigurationCollection collection, string key)
{
return (T)Convert.ChangeType(collection[key].Value, typeof(T));
}
}

public class KeyValueConfigurationCollection
{
public KeyValuePair<string, string> this [string key]
{
get
{
return new KeyValuePair<string, string>("KEY: " + key, "VALUE: Hi!");
}
}
}


Related Topics



Leave a reply



Submit