我如何使用反射调用扩展方法? [英] How do I invoke an extension method using reflection?

查看:98
本文介绍了我如何使用反射调用扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我AP preciate,类似的问题已经问过,但我奋力调用的LINQ的其中,在以下code方法。我期待利用反射动态调用此方法也是动态生成的其中,子句中使用的委托(或lambda)。这是一个简短code样品,一旦合作,将有助于形成一个跨preTED DSL是我建立的一部分。干杯。

 公共静态无效CallWhereMethod()
    {
        清单<&MyObject的GT; myObjects =新的List<&MyObject的GT;(){新MyObject的{名称=乔恩·辛普森}};
        System.Delegate NameEquals = BuildEqFuncFor<&MyObject的GT(姓名,乔恩·辛普森);
        [对象]的ATT =新对象[1];
        ATT以[0] = NameEquals;        VAR RET = typeof运算(名单<&MyObject的GT)。InvokeMember(去哪儿,BindingFlags.InvokeMethod,空,InstanceList,ATT以);
    }    公共静态Func键< T,BOOL> BuildEqFuncFor< T>(字符串道具,对象VAL)
    {
        返回T => t.GetType()。InvokeMember(道具,BindingFlags.GetProperty,
                                             空,T,NULL)== VAL;
    }


解决方案

至于其他人说,延伸的方法是编译器的魔力,可以送花儿给人使用VS右键,转到定义找到实现静态方法真正的类型。

从那里,它得到的相当多毛其中,超载,所以你需要找到你想要的签名相匹配的实际定义。 GetMethod 与泛型一些限制,所以你必须找到使用搜索的实际之一。

一旦你找到了方法,你必须使用 MakeGenericMethod 呼叫使的MethodInfo 具体。

下面是一个完整的工作示例:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用的System.Reflection;命名空间ConsoleApplication9 {
    类节目{        类为MyObject {
            公共字符串名称{;组; }
        }        公共静态无效CallWhereMethod(){
            清单<&MyObject的GT; myObjects =新的List<&MyObject的GT;(){
                新为MyObject {名称=乔恩·辛普森},
                新为MyObject {名称=杰夫阿特伍德}
            };
            FUNC<为MyObject,布尔> NameEquals = BuildEqFuncFor<&MyObject的GT(姓名,乔恩·辛普森);
            // Where方法生活在System.Linq的可枚举类型
            VAR whereMethods = typeof运算(System.Linq.Enumerable)
                .GetMethods(BindingFlags.Static | BindingFlags.Public)
                。凡(MI => mi.Name ==去哪儿);            Console.WriteLine(whereMethods.Count());
            // 2(有2种方法被称为凡)            MethodInfo的whereMethod = NULL;
            的foreach(在whereMethods VAR的MethodInfo){
                变种paramType = methodInfo.GetParameters()[1] .ParameterType;
                如果(paramType.GetGenericArguments()。COUNT()== 2){
                    //我们正在寻找Func键< TSource,布尔>中另一个有3
                    whereMethod = MethodInfo的;
                }
            }            //我们需要专注它
            whereMethod = whereMethod.MakeGenericMethod(typeof运算(为MyObject));            VAR RET = whereMethod.Invoke(myObjects,新的对象[] {m​​yObjects,NameEquals})为IEnumerable<为MyObject取代;            的foreach(在RET VAR项){
                Console.WriteLine(item.Name);
            }
            //输出乔恩·辛普森        }        公共静态Func键< T,BOOL> BuildEqFuncFor< T>(字符串道具,对象VAL){
            返回T => t.GetType()。InvokeMember(道具,BindingFlags.GetProperty,
                                                 空,T,NULL)== VAL;
        }        静态无效的主要(字串[] args){
            CallWhereMethod();
            Console.ReadKey();        }
    }
}

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;
    }

解决方案

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();

        }
    }
}

这篇关于我如何使用反射调用扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆