By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,885 Members | 1,474 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,885 IT Pros & Developers. It's quick & easy.

Firing Events using reflection

P: n/a
I looked high and low for code to do this and finally found some VB
code that did it right.

This is a C# flavor of it.

public event EventHandler<EventArgsMyEventToBeFired;

public void FireEvent(Guid instanceId, string handler)
{
EventArgs e = new EventArgs(instanceId);

MulticastDelegate eventDelagate =
(MulticastDelegate)GetType().GetField(handler,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue (this);

Delegate[] delegates = eventDelagate.GetInvocationList();

foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, new object[] { this, e
});
}
}

FireEvent("Some Data string arg that so happens to be a GUID",
"MyEventToBeFired");

Nov 22 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Firing events via reflection is always going to be dodgy as heck. In
particular, you have know way of knowing what the backer is. Is *might* be a
compiler-built field, but it might be a separate field I provide (perhaps
through a facade to an encapsulated class), or it might be via an
EventHandlerList, or about 17 other things. So you can't rely on reflection
to work unless you know what class you are dealing with and how the event is
implemented.

Even within a class you own, this would mandate some kind of switch or
dictionary; as a thought, it would be quite easy to create a variant of
EventHandlerList that works on Dictionary<string, EventHandler>, and lets
you do all of this just using the handler (string) directly as the key...
i.e. something like below...

But as a general principal, events should be fired from *within* a class,
not from outside.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;

public class MyData
{
public event EventHandler SomeEvent1 {
add { events.Add("SomeEvent1", value); }
remove { events.Remove("SomeEvent1", value); }
}
private readonly DelegateDictionary events = new DelegateDictionary();
public event EventHandler SomeEvent2
{
add { events.Add("SomeEvent2", value); }
remove { events.Remove("SomeEvent2", value); }
}
public event EventHandler SomeEvent3
{
add { events.Add("SomeEvent3", value); }
remove{ events.Remove("SomeEvent3", value); }
}
public void FireEvent(string name)
{
events.InvokeHandler(name, this);
}

}
class Program
{
static void Main()
{
MyData data = new MyData();
data.SomeEvent1 += new EventHandler(data_SomeEvent1);
data.SomeEvent2 += new EventHandler(data_SomeEvent2);
data.SomeEvent2 += new EventHandler(data_SomeEvent2);
data.FireEvent("SomeEvent2");
data.FireEvent("SomeEvent1");
data.FireEvent("SomeEvent3");// not subscribed
data.FireEvent("SomeDuffEvent");
}

static void data_SomeEvent1(object sender, EventArgs e)
{
Debug.WriteLine("data_SomeEvent1");
}
static void data_SomeEvent2(object sender, EventArgs e)
{
Debug.WriteLine("data_SomeEvent2");
}
}

public class DelegateDictionary
{
private readonly Dictionary<string, Delegatedata = new
Dictionary<string, Delegate>();

public void InvokeHandler(string key, object sender)
{
EventHandler handler = GetHandler(key);
if (handler != null) handler(sender, EventArgs.Empty);
}
public void Invoke(string key, params object[] parameters)
{
Delegate handler = this[key];
if (handler != null) handler.DynamicInvoke(parameters);
}
public EventHandler GetHandler(string key)
{
return (EventHandler) this[key];
}
public T Get<T>(string key)
{
return (T)(object)this[key];
}
public Delegate Get(string key)
{
return this[key];
}
public void Add(string key, Delegate handler)
{
if (handler == null) return;
Delegate current;
if (data.TryGetValue(key, out current))
{
data[key] = Delegate.Combine(current,handler);
}
else
{
data.Add(key, handler);
}
}
public void Remove(string key, Delegate handler)
{
if (handler == null) return;
Delegate current;
if (data.TryGetValue(key, out current))
{
data[key] = Delegate.Remove(current, handler);
}
}
public Delegate this[string key]
{
get
{
Delegate handler;
data.TryGetValue(key, out handler);
return handler;
}
}
}
Nov 22 '06 #2

P: n/a
Minor edit to clean up the dictionary when un-subscribing; you could even go
overboard and create / release the "data" field as the count of delegates
changes between 0 and >0

Still not sure it is a great idea *for calling from externally*, but an
interesting diversion ;-p

Marc

public void Remove(string key, Delegate handler) {
if (handler == null) return;
Delegate current;
if (data.TryGetValue(key, out current))
{
Delegate result = Delegate.Remove(current, handler);
if (result == null) {
data.Remove(key);
} else {
data[key] = result;
}
}
}
Nov 22 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.