Removing routed event handlers through reflection?

Background: I use WPF and C # (3.5) and work on an application that allows the user to view the form / window / usercontrol, which are already part of the compiled assembly. When they see it, they should be able to click on any control (buttons, text fields and even labels), a small pop-up editor should appear for this control, where they can enter a hint, helpID, etc. For this control.

Long and short: I need to emulate the basic design in WPF. This means that I need to do at least the following:

  • Download usercontrol / window from this assembly (no problem)
  • Create a usercontrol / window file (no problem)
  • Clear all signed EventHandlers for all its controls
  • Assign my own "ShowEditorPopup" EventHandler to each control (should not be a problem).

First of all, if anyone has suggestions for an easier or better route, please let me know. (Apparently, for WPF, there is no DesignHost component component (like, for example, I read .NET 2), so go out.)

I am stuck on a highlighted item - releasing all registered EventHandlers. After digging around some and getting into Reflector, I came up with this cool piece of dangerous code (here I'm just trying to get all the EventHandlers for a single button named someButton defined in XAML):

<Button Name="someButton" Click="someButton_Click"/>

Here's the code (you can run it from someButton_Click eventHandler if you want):

public void SomeFunction()
{
// Get the control Type
Type someButtonType = ((UIElement)someButton).GetType();

// Dig out the undocumented (yes, I know, it risky) EventHandlerStore
// from the control Type
PropertyInfo EventHandlersStoreType =  
        someButtonType.GetProperty("EventHandlersStore",  
        BindingFlags.Instance | BindingFlags.NonPublic);

// Get the actual "value" of the store, not just the reflected PropertyInfo
Object EventHandlersStore = EventHandlersStoreType.GetValue(someButton, null);

// Get the store type ...
Type storeType = EventHandlersStore.GetType();

// ... so we can pull out the store public method GetRoutedEventHandlers
MethodInfo GetEventHandlers =  
        storeType.GetMethod("GetRoutedEventHandlers",  
        BindingFlags.Instance | BindingFlags.Public);

// Reflector shows us that the method sig is this:
// public RoutedEventHandlerInfo[] GetRoutedEventHandlers(RoutedEvent routedEvent);

// So set up the RoutedEvent param
object[] Params = new object[] { ButtonBase.ClickEvent as RoutedEvent };
// I've also seen this for the param, but doesn't seem to make a difference:
// object[] Params = new object[] { someButton.ClickEvent };

// And invoke it ... and watch it crash!
GetEventHandlers.Invoke(someButton, Params);
}

Invoke, : Object (.. ). , :

GetEventHandlers.Invoke(Activator.CreateInstance(someButton.GetType()), Params);
// Also doesn't work...

GetEventHandlers MethodInfo, , , , Invoke.

, , RoutedEvent (, GetInvocationList(), , -, WPF RoutedEvents). , , .

? , / , :)

+3
3

, . EventManager.RegisterClassHandler() , ( , ) . , .

, , , , . , , , (, ), , , .

+3

GetEventHandlers.Invoke(EventHandlersStore , Params), .

+3

, :

// Get the control Type
Type controlViewType = ((UIElement)control).GetType();

// Dig out the undocumented (yes, I know, it risky) EventHandlerStore
// from the control Type
PropertyInfo EventHandlersStoreType =
controlViewType.GetProperty("EventHandlersStore",
BindingFlags.Instance | BindingFlags.NonPublic);

// Get the actual "value" of the store, not just the reflected PropertyInfo
Object EventHandlersStore = EventHandlersStoreType.GetValue(tree, null);
var miGetRoutedEventHandlers 
EventHandlersStore.GetType().GetMethod("GetRoutedEventHandlers", 
BindingFlags.Public | BindingFlags.Instance);
RoutedEventHandlerInfo[] res =   
(RoutedEventHandlerInfo[])miGetRoutedEventHandlers.Invoke(EventHandlersStore, 
new object[] { CheckedTreeViewItem.CheckedEvent });

, , , , . Window Page. , :   var parent = VisualTreeHelper.GetParent();   while (! (control is Window) & &! (control is Page))   {          parent = VisualTreeHelper.GetParent();   }

wtih:

res.[0].Handler.Method.Invoke(parent, new object[] { control, new RoutedEventArgs() }
0
source

Source: https://habr.com/ru/post/1710274/


All Articles