Check if this event is signed at runtime using reflection

Consider a class that has some events. This list of events will grow. Some of them are optional. Others are required.

To simplify some initial testing, I have a custom attribute that marks the event as mandatory. For instance:

    [RequiredEventSubscription("This event is required!")]
    public event EventHandler ServiceStarted;

So far so good. To check all events using reflection, I repeat the list of events and grab the user attributes. But I need a way to determine if the event is signed or not.

Without a reflex, ServiceStarted.GetInvocationList does the job. But the event should come from this list: var eventList = this.GetType (). GetEvents (). ToList ();

Is there a way to check if this event is signed from the list of events using reflection?

- [Update] - Here is a possible solution based on Ami's answer:

    private void CheckIfRequiredEventsAreSubscribed()
    {
        var eventList = GetType().GetEvents().ToList().Where(e => Attribute.IsDefined(e, typeof(RequiredEventSubscription)));

        StringBuilder exceptionMessage = new StringBuilder();
        StringBuilder warnMessage = new StringBuilder();

        foreach (var evt in eventList)
        {
            RequiredEventSubscription reqAttr = (RequiredEventSubscription) evt.GetCustomAttributes(typeof(RequiredEventSubscription), true).First();
            var evtDelegate = this.GetType().GetField(evt.Name, BindingFlags.Instance | BindingFlags.NonPublic);
            if (evtDelegate.GetValue(this) == null)
            {
                warnMessage.AppendLine(reqAttr.warnMess);
                if (reqAttr.throwException) exceptionMessage.AppendLine(reqAttr.warnMess);
            }
        }
        if (warnMessage.Length > 0)
            Console.WriteLine(warnMessage);
        if (exceptionMessage.Length > 0)
            throw new RequiredEventSubscriptionException(exceptionMessage.ToString());
    }

Many thanks!

+5
source share
1 answer

There are some serious design issues here. In general, there is no way to ask an object who his event subscribers are. It is very unusual that someone wants this functionality, but if you really want it, you must get classes to somehow expose this, for example, by implementing an interface using a method such as:

public IEnumerable<Delegate> GetSubscribers(string eventName);

, , , , . , , #, - ( ):

object o = ...

var unsubscribedEvents = 
  from e in o.GetType().GetEvents()
  where Attribute.IsDefined(e, typeof(RequiredEventSubscriptionAttribute))
  let field = o.GetType()
               .GetField(e.Name, BindingFlags.NonPublic | BindingFlags.Instance)
               .GetValue(o)
  where field == null
  select field;

var isValid = !unsubscribedEvents.Any();
+4

All Articles