GetMethod返回null

时间:2013-09-02 08:46:38

标签: c# asp.net reflection

我有一个asp.net网页。这是实现页面的类:

public partial class _Default : System.Web.UI.Page
    {
        private readonly string delegateName = "DynamicHandler";

        protected void Page_Load(object sender, EventArgs e)
        {
            EventInfo evClick = btnTest.GetType().GetEvent("Click");

            Type tDelegate = evClick.EventHandlerType;

            MethodInfo method = this.GetType().GetMethod("DynamicHandler", 
                BindingFlags.NonPublic | BindingFlags.Instance);

            Delegate d = Delegate.CreateDelegate(tDelegate, this, method);

            MethodInfo addHandler = evClick.GetAddMethod();
            Object[] addHandlerArgs = { d };
            addHandler.Invoke(btnTest, addHandlerArgs);


        }

        private void DynamicHandler(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }
    }

我正在尝试动态地连接一个事件处理程序。出于某种原因,method仍为空,我无法弄清楚原因。我以前做了很多次,但我无法弄清楚我错过了什么。

编辑:我发现this.GetType()返回页面ASP.default_aspx的类型,而不是实现页面的实际类型。我真的不知道怎么解决这个问题......

3 个答案:

答案 0 :(得分:6)

为了其他任何人的利益,如果您传递的参数与您尝试查找的方法的参数不匹配,GetMethod()也可以返回null。因此,例如,如果您要查找方法:

SomeMethod(int intParam, string stringParam)

您需要将参数类型传递给GetMethod

type.GetMethod("SomeMethod", new[] { typeof(int), typeof(string) });

或者,如果要指定特殊绑定标志:

type.GetMethod("SomeMethod", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int), typeof(string) }, null);

答案 1 :(得分:4)

正如您在编辑中发现的那样,实际的ASPX页面被编译成一个_Default继承的类(代码所在的位置)。因此,您需要DynamicHandler(至少)protected而不是private

同时指定BindingFlags.FlattenHierarchy

this.GetType().GetMethod("DynamicHandler", 
            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

<击>

答案 2 :(得分:3)

有两件事需要注意。

(1)使用时:

this.GetType()

或等效地只是GetType(),返回的类型是实际实例的实际运行时类型。由于_Default是非密封类,因此该类型可能比_Default更加派生(更专业的类型),即某些类具有_Default作为其直接或间接基础类。

如果你想要的是总是“常量”类型_Default,请使用typeof关键字,所以请使用:

typeof(_Default)

而不是GetType()。仅此一项就可以解决您的问题。

(2)即使您指定BindingFlags.NonPublic,也不会返回继承的 private成员。通过选择绑定标志,返回在同一个类(派生类)中声明的private方法,但不返回从基类继承的private方法。但是对于internalprotected成员,将返回在类本身中声明的那些成员以及在基类中声明的成员。

这可能有一定道理,因为private方法不是要从派生类调用的。

DynamicHandler方法的访问级别从private更改为protected(正如其他答案所示)足以解决您的问题,因为当您使用BindingFlags.NonPublic时会选择继承的受保护成员。

您仍然无法使用private获得继承的BindingFlags成员。相关主题C#: Accessing Inherited Private Instance Members Through Reflection。当然,可以编写一种搜索所有基类型的方法,如:

static MethodInfo GetPrivateMethod(Type type, string name)
{
    MethodInfo retVal;
    do
    {
        retVal = type.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
        if (retVal != (object)null)
            break;
        type = type.BaseType;
    } while (type != (object)null);
    return retVal;
}

仅此一项也可以解决您的问题。