Jon*_*son 31 c# linq reflection lambda delegates
我很感激之前已经提出了类似的问题,但我正在努力调用以下代码中的Linq Where方法.我希望使用反射动态调用此方法,并动态构建Where子句中使用的委托(或lambda).这是一个简短的代码示例,一旦工作,将有助于形成我正在构建的解释DSL的一部分.干杯.
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;
}
Run Code Online (Sandbox Code Playgroud)
Sam*_*ron 48
正如其他人所说,扩展方法是编译魔术,你可以一直使用VS右击,去定义找到实现静态方法的真实类型.
从那里,它变得相当毛茸茸.Where
重载,所以你需要找到匹配你想要的签名的实际定义.GetMethod
泛型类型有一些限制,因此您必须使用搜索找到实际类型.
找到方法后,您必须MethodInfo
使用该MakeGenericMethod
调用进行具体操作.
这是一个完整的工作样本:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Jor*_*ren 10
扩展方法实际上只是水下的静态方法.像foo.Frob(arguments)这样的扩展方法调用实际上只是SomeClass.Frob(foo,arguments).在Where方法的情况下,您正在寻找System.Linq.Enumerable.Where.因此,获取typeof Enumerable并调用Where on on.
归档时间: |
|
查看次数: |
22431 次 |
最近记录: |