This question is a followup to my question here:
http://groups.google.com/group/micro...c99e4742fe5fdb
I've been reading
http://www.yoda.arachsys.com/csharp/...ckchoice.shtml, and have
gotten a lot of great information from that page in general. So based
on what I've learned, I want to create a class that encapsulates the
safe use of an event, and I came up with the class at the end of this
post.
But it's not quite satisfying. I'd like to make it's strongly typed at
compile-time, and I don't know of a way to do that.
I first tried making it a generic class, with the type constrained to
be a delegate. That's when I learned that C# doesn't allow you to
constrain on a generic class based on the delegate type (compiler error
CS0702). So now I do type-checking at run-time, and clients can't see
the expected type via intellisense. Is there a better way?
It would also be nice if clients could add themselves to the handler
list using event-like syntax (i.e., the += operator), but it doesn't
seem that I'm allowed to override that operator. Am I missing
something?
Thanks for the excellent replies to the original question. Here's the
class as it exists now:
using System;
// The SafeEvent class is to ease the burden of using events in a
// thread-safe manner, which is surprisingly difficult.
// This code is adapted from the following webpage:
// http://www.yoda.arachsys.com/csharp/...ckchoice.shtml
public class SafeEvent
{
private object m_eventLock;
private Delegate m_event;
private Type m_eventType;
public SafeEvent(Type t)
{
if(!(t is Delegate))
{
throw new ArgumentException(
"SafeEvent requires a delegate type argument");
}
m_eventType = t;
m_eventLock = new object();
m_event = null;
}
public void Invoke(object[] args)
{
Delegate d;
lock(m_eventLock)
{
d = m_event;
}
if(d != null)
{
d.DynamicInvoke(args);
}
}
public void AddHandler(Delegate handler)
{
if(handler.GetType() != m_eventType)
{
throw new ArgumentException(
"Expected handler of type "
+ m_eventType.ToString());
}
lock(m_eventLock)
{
m_event = Delegate.Combine(m_event, handler);
}
}
public void RemoveHandler(Delegate handler)
{
if(handler.GetType() != m_eventType)
{
throw new ArgumentException(
"Expected handler of type "
+ m_eventType.ToString());
}
lock(m_eventLock)
{
m_event = Delegate.Remove(m_event, handler);
}
}
}