C# supports implicit/explicit conversions to Delegates.
Yes, big news. I was very surprised when I gave this a shot. It’s really just one of those things you really don’t expect to work. So how does this help us? I am sure you are quite sick of writing the following code (the same stuff applies to WPF, you just need to access it via the Dispatch member):
void _items_CollectionChanged(object sender, CollectionChangedEventArgs<ConnectionListItem> e)
{
if (InvokeRequired)
{
Invoke(new EventHandler<CollectionChangedEventArgs<ConnectionListItem>>( _items_CollectionChanged ), sender, e);
return;
}
}
The ‘big news’ allows us to do all the heavy lifting for the dispatch BeginInvoke in one simple class (this is a first try – I’ll get round to reviewing it later on).
/// <summary>
/// Represent a wrapper for a delegate.
/// </summary>
/// <typeparam name="T">The type of event args.</typeparam>
public class InvokeEventWrapper<T>
where T : EventArgs
{
private EventHandler<T> _apparantHandler;
private EventHandler<T> _rawHandler;
private Control _parent;
/// <summary>
/// Initializes a new instance of the <see cref="InvokeDelegateWrapper<T>"/> class.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="handler">The handler.</param>
public InvokeEventWrapper(EventHandler<T> handler)
: this(null, handler)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="InvokeDelegateWrapper<T>"/> class.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="handler">The handler.</param>
public InvokeEventWrapper(Control parent, EventHandler<T> handler)
{
if (handler == null)
throw new ArgumentNullException("handler");
if (parent == null)
parent = (Control)handler.Target;
_parent = parent;
_rawHandler = handler;
_apparantHandler = new EventHandler<T>(Raise);
}
/// <summary>
/// Performs an implicit conversion from <see cref="SharedTerminals.InvokeDelegateWrapper<T>"/> to <see cref="System.EventHandler<T>"/>.
/// </summary>
/// <param name="wrapper">The wrapper.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator EventHandler<T>(InvokeEventWrapper<T> wrapper)
{
return wrapper._apparantHandler;
}
/// <summary>
/// Raises the event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
private void Raise(object sender, T e)
{
if (_parent.InvokeRequired)
_parent.BeginInvoke(_rawHandler, sender, e);
else
_rawHandler(sender, e);
}
}
Using it is pretty simple:
- Navigate to the event in Intellisense.
- Type +=.
- Press Tab.
- Replace EventHandler with InvokeEventWrapper.
So in the end all of that ugly code becomes:
_items.CollectionChanged += new InvokeEventWrapper<CollectionChangedEventArgs<ConnectionListItem>>( _items_CollectionChanged );
You will need to hold onto a reference for that wrapper if you wish to unsubscribe from the event (one of the things I need to look at).





