C# Using Reflection to subscribe to Events

Chris M 1 Reputation point
2021-11-19T17:28:11.487+00:00

I have a program where i am using Reflection to load classes dynamically based on a text file.

When i run my code i can get all the classes, methods and Events printing to screen and can even Invoke the methods.

I added all events to a Dictionary and i want to enumerate through them and then create a Event Handler to get the data sent by the event.

here is my method for getting the events to a dictionary:

  private Dictionary<string, EventInfo> RetrieveEvents(string label, string type)
        {
            try
            {
                this.displaysAssembly = Assembly.LoadFrom(Path.Combine(Directory.GetApplicationDirectory(), "Framework.DisplayDrivers.dll"));

                string assembly = string.Format("Framework.DisplayDrivers.{0}", type);
                Type cswitcher = displaysAssembly.GetType(assembly);

                fullClass = cswitcher;
                Dictionary<string, EventInfo> ekvp = new Dictionary<string, EventInfo>();
                List<EventInfo> eventInfos = cswitcher.GetEvents().Where(e => HasInformationAttribute(e)).ToList();

                foreach (var e in eventInfos)
                {                   
                    if (!ekvp.ContainsKey(label))
                    {
                        ekvp.Add(e.Name, e);
                    }

                }

                return (ekvp);
            }
            catch (MissingMethodException e)
            {
                ErrorLog.Error(LogHeader + "Unable to create Display. No constructor: {0}", e.Message);

            }
            catch (ArgumentException e)
            {
                ErrorLog.Error(LogHeader + "Unable to create Display. No type: {0}", e.Message);

            }
            catch (NullReferenceException e)
            {
                ErrorLog.Error(LogHeader + "Unable to create Display. No match: {0}", e.Message);

            }


            return null;
        }

if I print out the Dictionary i can see the events by Key and Value.

but i cannot seem to create an Event handler. I have tried many options including:

foreach(var evnt in d._projectors._events)
                    {
                        EventInfo ev = evnt.Value;


                        try
                        {

                            // this id not work
                            object classInstance = Activator.CreateInstance(d._projectors.fullClass);
                            ev.AddEventHandler(classInstance, new EventHandler(DisplayChangeEvents.DisplayMuteChangedEvent));

                            // this did not work either

                            if (d._projectors._events.TryGetValue("OnPowerStateRecieved", out ev))
                            {
                                ev.AddEventHandler(ev.Name, new EventHandler(DisplayChangeEvents.DisplayPowerChangedEvent));                               
                            }

                        }
                        catch (Exception ex)
                        {

                            ErrorLog.Error("Error creating event handers :  " +  ex.Message + "\r");
                        }                      
                    }

i am trying to subscibe to the event and handle the data in another class named "DisplayChangeEvents".

i have been trying for 2 days to get this and its the last piece i need to get the program working as expected.

Thanks in advance

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Chris M 1 Reputation point
    2021-11-19T18:13:21.473+00:00

    so in the class that retrieves the events i changed the code to this to cast the class to an object.

     try
                {
                    this.displaysAssembly = Assembly.LoadFrom(Path.Combine(Directory.GetApplicationDirectory(), "Framework.DisplayDrivers.dll"));
    
                    string assembly = string.Format("Framework.DisplayDrivers.{0}", type);
                    Type cswitcher = displaysAssembly.GetType(assembly);
    
                    fullClass =  displaysAssembly.GetType(assembly);
    
                    Dictionary<string, EventInfo> ekvp = new Dictionary<string, EventInfo>();
                    List<EventInfo> eventInfos = cswitcher.GetEvents().Where(e => HasInformationAttribute(e)).ToList();
    
                    foreach (var e in eventInfos)
                    {                   
                        if (!ekvp.ContainsKey(label))
                        {
                            ekvp.Add(e.Name, e);
                        }
    
                    }
    
                    return (ekvp);
                }
    

    then in the method trying to create the subscriptions i changed it to :

     foreach (var d in DisplayCollection.displayList)
                    {
    
                        foreach(var evnt in d._projectors._events)
                        {
                            EventInfo ev = evnt.Value;
    
    
                            try
                            {
    
                                if (evnt.Key == "OnPowerStateRecieved")
                                {
                                    ev.AddEventHandler(d._projectors.fullClass, new EventHandler(DisplayChangeEvents.DisplayPowerChangedEvent));
                                }
                                else if (evnt.Key == "OnMuteStateRecieved")
                                {
                                    ev.AddEventHandler(d._projectors.fullClass, new EventHandler(DisplayChangeEvents.DisplayMuteChangedEvent));
                                }
    

    however i get a exception of: Error creating event handers : Specified cast is not valid.

    0 comments No comments

  2. Bruce (SqlWork.com) 61,731 Reputation points
    2021-11-23T15:40:23.183+00:00

    The delegate must have the correct signature ( parameter types) to be added. In the doc, they dynamically create a handler with the correct signature via code generation.

    See docs

    https://learn.microsoft.com/en-us/dotnet/api/system.reflection.eventinfo.addeventhandler?view=net-6.0