开发者

Check if a given event is subscribed, during runtime, using reflection

Consider a class that has some events. This event list is going to grow. Some are optional. Others are required.

To simplify some initial validation I have a custom attribute that marks an event as a required one. For example:

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

So far so good. To validate all events, using reflection I iterate the event list and grab the custom attributes. But I need a way to determine if the event is subscribed or not.

Without reflection the ServiceStarted.GetInvocationList does the job. But the event must come from this list: var eventList = this.GetType().GetEvents().ToList();

Is there any way to check if a given event, from an event list, is subscribed using reflection?

--[Update]-- Here's 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!!


There are some major design issues here. In general, there's no way to ask an object who its events' subscribers are. It's highly unusual that anyone would want this functionality, but if you really want it, you should get classes to somehow expose this, for example, by implementing an interface with a method such as:

public IEnumerable<Delegate> GetSubscribers(string eventName);

Anyway, to answer the question as asked, you can use reflection, but only if you know exactly how the subscribers are being maintained. For example, assuming that all events are implemented with the current implementation of C# field-like events, you can do something like (strongly discouraged):

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();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜