简体   繁体   中英

C# Using Reflection to subscribe to Events

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

based on a suggestion i updated the code in the foreach loop to:

 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));
                        }
                        // this id not work
                        // object classInstance = Activator.CreateInstance(d._projectors.fullClass);
                        //  ev.AddEventHandler(classInstance, new EventHandler(DisplayChangeEvents.DisplayMuteChangedEvent));

                        //ev.AddEventHandler(d._projectors.fullClass, 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));                               
                        //}

                    }

get the following exception:

Specified cast is not valid.

the class that is creating the events looks like this:

 private static event EventHandler<PowerStateEventsArgs> _onPowerStateRecieved = delegate { };
    [Information(Description = "Power Event")]

    public static event EventHandler<PowerStateEventsArgs> OnPowerStateRecieved
    {
        add
        {
            if (!_onPowerStateRecieved.GetInvocationList().Contains(value))
            {
                 _onPowerStateRecieved += value;
            }
        }
        remove
        {
            _onPowerStateRecieved -= value;
        }
    }

the event that fires the event looks like this:

 if (i == 1)
                {
                    _onPowerStateRecieved(null, new PowerStateEventsArgs(true));
                }

this logic works in all other programs except when i am trying to reflection to create the classes dynamically.

I took the advice of the folks here and cut back my code and went back to basics with event handlers. I was able to load the drivers in my code via reflection and invoke the members, However I was unable to get the events working the way that I thought they would. I was able to just add in a switch-case and see which drivers were loaded and subscribed to the events manually. Not ideal but if this group had not told me to cut back and go back to basics I would never have gotten as far as I did. Thank you all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM