4

我有一个 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而不是实现页面的实际类型。我真的不知道如何解决这个问题......

4

3 回答 3

7

为了其他人的利益,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);
于 2014-12-27T23:34:43.763 回答
4

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

还要指定BindingFlags.FlattenHierarchy

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

于 2013-09-02T09:08:08.467 回答
3

有两件事需要注意。

(1)使用时:

this.GetType()

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

如果您想要的始终是“常量”类型_Default,请使用typeof关键字,因此请使用:

typeof(_Default)

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

(2)即使指定BindingFlags.NonPublic继承 private的成员也不会返回。通过选择绑定标志,private将返回在同一类(派生类)中声明的方法,但private不返回从基类继承的方法。但是,使用internalandprotected成员时,将返回在类本身中声明的成员和在基类中声明的成员。

这可能有些道理,因为private方法并不意味着从派生类中调用。

DynamicHandler将您的方法的访问级别从更改private为例如protected(如另一个答案中所建议的)足以解决您的问题,因为在您使用时选择了继承的受保护成员BindingFlags.NonPublic

仍然很有趣的是,您无法private使用BindingFlags. 相关线程C#:通过反射访问继承的私有实例成员。当然,可以编写一个搜索所有基本类型的方法,例如:

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

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

于 2013-09-02T10:52:00.850 回答