lundi 2 mars 2020

Add event handler using reflection

I have a .json file with so-called commands:

"Commands":[{
   "EventName": "MouseLeftButtonUp",
   "MethodToExecute": "NextJson",
   "Args": "Next.json"
},{
   "EventName": "MouseRightButtonUp",
   "MethodToExecute": "CloseApp"
}

I deserialize this json to this class:

    public class Command
    {
        [JsonPropertyName("EventName")]
        public string EventName { get; set; }

        [JsonPropertyName("MethodToExecute")]
        public string MethodToExecute { get; set; }

        [JsonPropertyName("Args")]
        public string Args { get; set; }

        /*Methods*/
    }

EventName is a name of UIElement class events. MethodToExecute is a name of method to call, when event triggered. Args are the args, passed to the MethodToExecute.

I don't want my users to be able to call any method in the application, so I don't use reflection to get MethodInfo, instead I create Dictionary: Dictionary<string, Delegate> MethodsDictionary. The key in this dictionary is the name of method (MethodToExecute from Command class), and the value is something like this:

MethodsDictionary.Add(nameof(CloseApp), new Action(CloseApp));
MethodsDictionary.Add(nameof(NextJson), new Action<string>(NextJson));

Without using reflection, I'd added the event handler like this: button.MouseLeftButtonUp += (sender, args) => MethodsDictionary[command.MethodToExecute].DynamicInvoke(command.Args);, but I'd like to make a dynamic binding of events. Well, of course I can make it through ugly switch-case on command.Name property, but I still would like to try the solution with reflection. The solutuion, as I see it, should looke something like:

foreach (var command in commands)
{
    command.Bind(uielement, MethodsDictionary[command.MethodToExecute]);
}

//And command.Bind method is like:

public void Bind(UIElement uielement, Delegate methodToExecute)
{
    //I know there's no such method like GetEventHandler, just an example
    var handler = uielement.GetEventHandler(EventName);
    handler += methodToExecute.DynamicInvoke(Args);
}

I searched through several pretty similar questions:

Subscribe to an event with Reflection

https://social.msdn.microsoft.com/Forums/vstudio/en-US/d7f184f1-0964-412a-8659-6759a0e2db83/c-reflection-problem-subscribing-to-event?forum=netfxbcl

https://docs.microsoft.com/en-us/dotnet/framework/reflection-and-codedom/how-to-hook-up-a-delegate-using-reflection

AddEventHandler using reflection

Add Event Handler using Reflection ? / Get object of type?

But these doesn't help me to solve the problem the way I want to. I tried some of the solutions above, but they didn't work out for me, failing with different exceptions.





Aucun commentaire:

Enregistrer un commentaire