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