Created
September 17, 2009 01:57
-
-
Save JeffreyZhao/188304 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class EventFactory | |
{ | |
public static DelegateEvent<T> Create<T>(Expression<Func<T>> eventExpr) | |
{ | |
return new DelegateEvent<T>(eventExpr); | |
} | |
} | |
public class DelegateEvent<TDelegate> | |
{ | |
public DelegateEvent(Action<TDelegate> add, Action<TDelegate> remove) | |
{ | |
this.CheckDelegateType(); | |
if (add == null) throw new ArgumentNullException("add"); | |
if (remove == null) throw new ArgumentNullException("remove"); | |
this.m_addHandler = add; | |
this.m_removeHandler = remove; | |
} | |
private void CheckDelegateType() | |
{ | |
if (!typeof(Delegate).IsAssignableFrom(typeof(TDelegate))) | |
{ | |
throw new ArgumentException("TDelegate must be an Delegate type."); | |
} | |
} | |
public DelegateEvent(Expression<Func<TDelegate>> eventExpr) | |
{ | |
this.CheckDelegateType(); | |
// () => obj.EventName | |
if (eventExpr == null) throw new ArgumentNullException("eventExpr"); | |
// obj.EventName | |
var memberExpr = eventExpr.Body as MemberExpression; | |
if (memberExpr == null) | |
{ | |
throw new ArgumentNullException("eventExpr", "Not an event."); | |
} | |
object instance = null; | |
// obj | |
if (memberExpr.Expression != null) | |
{ | |
try | |
{ | |
// () => obj | |
var instanceExpr = Expression.Lambda<Func<object>>(memberExpr.Expression); | |
instance = instanceExpr.Compile().Invoke(); | |
} | |
catch (Exception ex) | |
{ | |
throw new ArgumentNullException("eventExpr is not an event", ex); | |
} | |
} | |
this.BindEvent(memberExpr.Member.DeclaringType, instance, memberExpr.Member.Name); | |
} | |
public DelegateEvent(Type type, string eventName) | |
{ | |
this.CheckDelegateType(); | |
if (type == null) throw new ArgumentNullException("type"); | |
if (String.IsNullOrEmpty(eventName)) throw new ArgumentNullException("eventName"); | |
this.BindEvent(type, null, eventName); | |
} | |
public DelegateEvent(object obj, string eventName) | |
{ | |
this.CheckDelegateType(); | |
if (obj == null) throw new ArgumentNullException("obj"); | |
if (String.IsNullOrEmpty(eventName)) throw new ArgumentNullException("eventName"); | |
this.BindEvent(obj.GetType(), obj, eventName); | |
} | |
private void BindEvent(Type type, object obj, string eventName) | |
{ | |
var eventInfo = type.GetEvent(eventName, | |
BindingFlags.Public | BindingFlags.NonPublic | | |
(obj == null ? BindingFlags.Static : BindingFlags.Instance)); | |
if (eventInfo == null) | |
{ | |
throw new ArgumentException( | |
String.Format("Event {0} is missing in {1}", | |
eventName, type.FullName)); | |
} | |
if (eventInfo.EventHandlerType != typeof(TDelegate)) | |
{ | |
throw new ArgumentException( | |
String.Format("Type of event {0} in {1} is mismatched with {2}.", | |
eventName, type.FullName, typeof(TDelegate).FullName)); | |
} | |
this.m_addHandler = h => eventInfo.AddEventHandler(obj, (Delegate)(object)h); | |
this.m_removeHandler = h => eventInfo.RemoveEventHandler(obj, (Delegate)(object)h); | |
} | |
private Action<TDelegate> m_addHandler; | |
private Action<TDelegate> m_removeHandler; | |
public DelegateEvent<TDelegate> AddHandler(TDelegate handler) | |
{ | |
this.m_addHandler(handler); | |
return this; | |
} | |
public DelegateEvent<TDelegate> RemoveHandler(TDelegate handler) | |
{ | |
this.RemoveHandler(handler); | |
return this; | |
} | |
public static DelegateEvent<TDelegate> operator +(DelegateEvent<TDelegate> ev, TDelegate handler) | |
{ | |
return ev.AddHandler(handler); | |
} | |
public static DelegateEvent<TDelegate> operator -(DelegateEvent<TDelegate> ev, TDelegate handler) | |
{ | |
return ev.RemoveHandler(handler); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment