Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I invoke an extension method using reflection?

I appreciate that similar questions have been asked before, but I am struggling to invoke the Linq Where method in the following code. I am looking to use reflection to dynamically call this method and also dynamically build the delegate (or lambda) used in the Where clause. This is a short code sample that, once working, will help to form part of an interpreted DSL that I am building. Cheers.

    public static void CallWhereMethod()     {         List<MyObject> myObjects = new List<MyObject>(){new MyObject{Name="Jon Simpson"}};         System.Delegate NameEquals = BuildEqFuncFor<MyObject>("Name", "Jon Simpson");         object[] atts = new object[1] ;         atts[0] = NameEquals;          var ret = typeof(List<MyObject>).InvokeMember("Where", BindingFlags.InvokeMethod, null, InstanceList,atts);     }      public static Func<T, bool> BuildEqFuncFor<T>(string prop, object val)     {         return t => t.GetType().InvokeMember(prop,BindingFlags.GetProperty,                                              null,t,null) == val;     } 
like image 935
Jon Simpson Avatar asked Sep 20 '09 23:09

Jon Simpson


People also ask

How do you call an extension method?

To define and call the extension methodDefine a static class to contain the extension method. The class must be visible to client code. For more information about accessibility rules, see Access Modifiers. Implement the extension method as a static method with at least the same visibility as the containing class.

How extension method is achieved?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.

Can you add extension methods to an existing static class?

No. Extension methods require an instance of an object.

What is the role of an extension method when would you use it?

Extension methods enable developers to add custom functionality to data types that are already defined without creating a new derived type. Extension methods make it possible to write a method that can be called as if it were an instance method of the existing type.


2 Answers

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();          }     } } 
like image 64
Sam Saffron Avatar answered Sep 16 '22 12:09

Sam Saffron


Extension methods are really just static methods underwater. An extension method call like foo.Frob(arguments) is really just SomeClass.Frob(foo, arguments). In the case of the Where method, you're looking for System.Linq.Enumerable.Where. So get the typeof Enumerable and invoke Where on that.

like image 44
Joren Avatar answered Sep 18 '22 12:09

Joren