Question

My constructor parses its instance for events with a certain attribute:

_EventAttributes = from EventDescriptor a in TypeDescriptor.GetEvents(this)
            let attribute = a.Attributes[typeof(MyAttribute)] as MyAttribute
            where attribute != null
            select new EventAttributeTuple { Event = a, Attribute = attribute };

Later in the code i want to check whether the corresponding event is null (nobody is interested in the event) to decide whether or not i have to write it in my XML output:

//write events
foreach (var attr in _EventAttributes)
{
    if (check corresponding attr.Event object is null)
    {
        writer.WriteAttributeString(attr.Attribute.Name, GetRPCAdress(attr.Event.Name));
    }
}

EDIT:

Getting the EventInfo is also quite easy:

var evtInfo = this.GetType().GetEvent(attr.Event.Name);

But still, i don't know how to check whether the event has subscribers or not.

EDIT2:

After looking at the generated code with dotPeek, I think there is no chance to access any field here:

    //original code
    [MyAttribute("onclick")]
    public event EventHandler<MouseArg> Click;

    //generated code
    [MyAttribute("onclick")]
    public event EventHandler<MouseArg> Click
    {
      add
      {
        EventHandler<MouseArg> eventHandler = this.Click;
        EventHandler<MouseArg> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<MouseArg>>(ref this.Click, comparand + value, comparand);
        }
        while (eventHandler != comparand);
      }
      remove
      {
        EventHandler<MouseArg> eventHandler = this.Click;
        EventHandler<MouseArg> comparand;
        do
        {
          comparand = eventHandler;
          eventHandler = Interlocked.CompareExchange<EventHandler<MouseArg>>(ref this.Click, comparand - value, comparand);
        }
        while (eventHandler != comparand);
      }
    }

There may be a chance, if i handle all of the event add/remove operations myself, but that seems very tedious. Anyone has a better idea?

EDIT3:

I got it, i was using this.GetType() which does not give me the declaring type but was a subclass of the class which declares the event, hence i was not able to retrieve the field.

It now works like this:

var evtValue = attr.Event.ComponentType.GetField(attr.Event.Name, 
               BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this);
Was it helpful?

Solution

Sorry, this is impossible in general case, for instance:

  class CounterExample {
    public event EventHandler MyEvent {
      add {
        // You can't control me here: whether I truly add an event or not 
        // and even if I always add the event - where I store it
      }
      remove {
        // You can't control me here: whether I truly remove an event or not
        // and even if I always remove the event - from where I delete it
      }
    }
  }

But in many cases you can do a hack (be careful though):

  class SimpleCase { 
    // Usual event realization (default add and remove accessors)
    public event EventHandler MyEvent; 
  }

  ...
  SimpleCase cs = new SimpleCase();
  cs.MyEvent += ...
  ...

  // Since MyEvent has default accessors, lets check the default storage: 
  FieldInfo fi = cs.GetType().GetField("MyEvent", BindingFlags.NonPublic | BindingFlags.Instance);
  Boolean myEventAssigned = !Object.ReferenceEquals(fi.GetValue(cs), null);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top