如何使用reflection调用扩展方法?

我很感激之前已经提出了类似的问题,但我正在努力调用以下代码中的Linq Where方法。 我希望使用reflection动态调用此方法,并动态构建Where子句中使用的委托(或lambda)。 这是一个简短的代码示例,一旦工作,将有助于形成我正在构建的解释DSL的一部分。 干杯。

public static void CallWhereMethod() { List myObjects = new List(){new MyObject{Name="Jon Simpson"}}; System.Delegate NameEquals = BuildEqFuncFor("Name", "Jon Simpson"); object[] atts = new object[1] ; atts[0] = NameEquals; var ret = typeof(List).InvokeMember("Where", BindingFlags.InvokeMethod, null, InstanceList,atts); } public static Func BuildEqFuncFor(string prop, object val) { return t => t.GetType().InvokeMember(prop,BindingFlags.GetProperty, null,t,null) == val; } 

正如其他人所说,扩展方法是编译魔术,你可以一直使用VS右击,去定义找到实现静态方法的真实类型。

从那里,它变得相当毛茸茸Where重载,因此您需要找到与您想要的签名匹配的实际定义。 GetMethod对generics类型有一些限制,因此您必须使用搜索找到实际类型。

找到方法后,必须使用MakeGenericMethod调用使MethodInfo具体化。

这是一个完整的工作样本:

 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 myObjects = new List() { new MyObject { Name = "Jon Simpson" }, new MyObject { Name = "Jeff Atwood" } }; Func NameEquals = BuildEqFuncFor("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, 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; foreach (var item in ret) { Console.WriteLine(item.Name); } // outputs "Jon Simpson" } public static Func BuildEqFuncFor(string prop, object val) { return t => t.GetType().InvokeMember(prop, BindingFlags.GetProperty, null, t, null) == val; } static void Main(string[] args) { CallWhereMethod(); Console.ReadKey(); } } } 

扩展方法实际上只是水下的静态方法。 像foo.Frob( arguments )这样的扩展方法调用实际上只是SomeClass.Frob(foo, arguments )。 在Where方法的情况下,您正在寻找System.Linq.Enumerable.Where。 因此,获取typeof Enumerable并调用Where on on。

我有点过时和迟到但如果你需要调用IEnumerable类型的Linq扩展,这可能对你有所帮助。

IEnumerable test = obj as IEnumerable;

然后可能测试obj如果不是null和

int count = test.Count()

对我来说非常好。

您的代码示例有点令人困惑……除非MyObject是可枚举的。

使用reflection你必须调用System.Linq.Enumerable上的Where,传入你要在其中预先形成的枚举。

扩展方法是ac#编译器技巧,它们在相关类型中不存在。 它们(这些特定的)存在于System.Linq名称空间内的静态类中。 我建议在reflection器中反映这一点,然后调用这些类型的reflection。