为什么我无法通过反射获取控件的 MouseDown 事件



我尝试使用 .NET 反射删除事件处理程序。 当我使用自己的测试类(将参数从控制那个更改为测试类那个(时,它可以工作。

但是当我想使用 WindowsForms 控件执行此操作时,我无法获取事件的公共字段(严格来说,我没有任何公共实例字段(。 我的TestClass和WindowsForms控件有什么不同。 "MouseDown"事件和我的测试类中的事件都是公开的。

static void  RemoveHandler( Control that )
{
//adding an eventhandler for testing
that.MouseDown += (obj,arg) => { };
string eventName = "MouseDown";
//this works, but I need the Field, to get the Invocationlist
var testEventInfo = that.GetType().GetEvent( eventName, BindingFlags.Public | BindingFlags.Instance );
if ( testEventInfo != null )
{
//this fails, Declaring Type of my Event "MouseDown" is Control  testEventFieldInfo stays null
var testEventFieldInfo = testEventInfo.DeclaringType.GetField( testEventInfo.Name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField );
//trying to get all public events fails too, fields is always empty
// var fields = testEventInfo.DeclaringType.GetFields( BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField );
if ( testEventFieldInfo != null )
{
var testEventFieldValue = (System.Delegate)testEventFieldInfo.GetValue( that );
if ( testEventFieldValue != null ) // if its null no Delegates are hooked
{
var invocationList = testEventFieldValue.GetInvocationList();
//var removeMethod = testEventInfo.GetRemoveMethod();
foreach ( var eventHandlerDelegate in invocationList )
{
testEventInfo.RemoveEventHandler( that, eventHandlerDelegate );
}
}
}
}
}

我尝试的是处理继承问题。 (TestClass 是一个驱动类,基类声明事件( 发现.GetEvent 也从所有基类获取事件,但 GetField 没有,所以我添加了对 .声明字段的类型。所有这些都适用于我的 TestClass,但不适用于 Control 派生类型(即按钮或列表框(

我还发现,有一个字段"EventMouseDown",它是非公共和静态的。但是我找不到任何有关此的文档。我迷上的名字是"MouseDown">

所以也许你知道,我缺乏知识的地方。 谢谢。

也许,我刚刚找到了一种方法,它似乎有效,但我不知道为什么(让我知道,如果你知道这个 WindowsFormsEvent 是如何构建的( 答案是对本文的修改: GetField 无法获取事件点击

//Important is, that the Field is NoPublic and Static and is Named "Event~"
//What does the .GetValue(null)
var field = testEventInfo.DeclaringType.GetField( "EventMouseDown", BindingFlags.NonPublic | BindingFlags.Static ).GetValue( null );
//Then you take the so called EventHandlerList which is also Static 
// and NoPublic and use your instance to get the Value of it
var eventList = (EventHandlerList)testEventInfo.DeclaringType.GetProperty( "Events", BindingFlags.Instance | BindingFlags.NonPublic ).GetValue( that );
//the trick is now, to use the field as a key for the eventList
var mouseDownEvent = eventList[field];
if ( mouseDownEvent != null)
{
var invList = mouseDownEvent.GetInvocationList();   
foreach (var eventHandlerDelegate in invList )
{
testEventInfo.RemoveEventHandler( that, eventHandlerDelegate );
}
}
//Now the invocation List ist empty
var modifiedEventList = (EventHandlerList)testEventInfo.DeclaringType.GetProperty( "Events", BindingFlags.Instance | BindingFlags.NonPublic ).GetValue( that );
var modifiedMouseDownEvent = eventList[field];
//modifiedMouseDownEvent is null now, no delegate is attached anymore

但是为什么事件被命名为"EventMouseDown",并且它是NoPublic和Static?我不知道,它只是对我有用。 也许我可以保存处理程序并保存它们,并在以后需要时将它们钩回。

最新更新