我有一个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
的类型,而不是实现页面的实际类型。我真的不知道怎么解决这个问题......
答案 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
方法。但是对于internal
和protected
成员,将返回在类本身中声明的那些成员以及在基类中声明的成员。
这可能有一定道理,因为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;
}
仅此一项也可以解决您的问题。