-1

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);
thalm
  • 2,738
  • 2
  • 35
  • 49

1 Answers1

1

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);
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • i tried: FieldInfo fi = cs.GetType().GetField("MyEvent", BindingFlags.NonPublic | BindingFlags.Instance); but 'fi' is always null, means there is no field i can access... i also tried with GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) to get all fields, but there was no field which was connected to my event. – thalm Jun 28 '13 at 17:21
  • There's no guarantee that hack will do: if add/remove accessors are explicit it wouldn't work. Unfortunately many Window Controls (TextBox, Panel etc) have explicit accessors – Dmitry Bychenko Jun 28 '13 at 17:24
  • the event is part of my own class and is defined as in your SimpleCase class. – thalm Jun 28 '13 at 17:25
  • Could you, please, provide some code? I've played (adding and removing methods, fields, events etc.) with my own SimpleCase (on C# 4.5) and it does work. – Dmitry Bychenko Jun 28 '13 at 17:37
  • 1
    Well, the very first line in "add" accessor for "public event EventHandler Click" is "EventHandler eventHandler = this.Click" which is getting field/propery value, and the field/propery has "Click" name. Could you, please, check if there's "Click" property since there's no "Click" field. – Dmitry Bychenko Jun 28 '13 at 18:03