Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public abstract class EventHandle : IDisposable
- {
- public static EventHandle<TTarget, THandler> Create<TTarget, THandler>(
- TTarget target,
- THandler callback,
- Action<TTarget, THandler> add,
- Action<TTarget, THandler> remove)
- where TTarget : class
- where THandler : ICloneable, ISerializable
- {
- return new EventHandle<TTarget, THandler>(target, callback, add, remove);
- }
- public abstract object Target { get; }
- public abstract void Dispose();
- }
- public class EventHandle<TTarget, THandler> : EventHandle
- where TTarget : class
- where THandler : ICloneable, ISerializable
- {
- #region Static
- static Func<Proxy, THandler> _createHandler;
- static EventHandle()
- {
- if (typeof(Delegate).IsAssignableFrom(typeof(THandler)))
- {
- var invokeMethod = typeof(THandler).GetMethod("Invoke");
- var invokeMethodParamters = invokeMethod.GetParameters();
- var callbackField = typeof(Proxy).GetField("Callback");
- var disposedField = typeof(Proxy).GetField("Disposed");
- var @parameters = new ParameterExpression[invokeMethodParamters.Length];
- for (int i = 0; i < @parameters.Length; i++)
- {
- @parameters[i] =
- Expression.Parameter(invokeMethodParamters[i].ParameterType);
- }
- var @proxy =
- Expression.Parameter(typeof(Proxy));
- var @callback =
- Expression.Variable(typeof(THandler));
- var @getCallback =
- Expression.Assign(
- @callback,
- Expression.TypeAs(
- Expression.Property(
- Expression.Field(
- @proxy,
- callbackField),
- "Target"),
- typeof(THandler)));
- var @tryInvoke =
- Expression.IfThen(
- Expression.Not(
- Expression.Field(
- @proxy,
- "Disposed")),
- Expression.IfThenElse(
- Expression.NotEqual(
- @callback,
- Expression.Constant(null, typeof(THandler))),
- Expression.Invoke(
- @callback,
- @parameters),
- Expression.Call(
- @proxy,
- "Dispose",
- new Type[0])));
- _createHandler =
- Expression.Lambda<Func<Proxy, THandler>>(
- Expression.Lambda<THandler>(
- Expression.Block(
- new ParameterExpression[]
- {
- @callback,
- },
- new Expression[]
- {
- @getCallback,
- @tryInvoke,
- }),
- @parameters),
- @proxy)
- .Compile();
- }
- }
- #endregion
- private Proxy _proxy;
- private THandler _callback;
- public EventHandle(TTarget target, THandler callback, Action<TTarget, THandler> add, Action<TTarget, THandler> remove)
- {
- if (!typeof(Delegate).IsAssignableFrom(typeof(THandler))) throw new ArgumentException("delegate type expected", "T");
- if (target == null) throw new ArgumentNullException("add");
- if (callback == null) throw new ArgumentNullException("add");
- if (add == null) throw new ArgumentNullException("add");
- if (remove == null) throw new ArgumentNullException("remove");
- _proxy = new Proxy(target, callback, add, remove);
- _callback = callback;
- }
- ~EventHandle()
- {
- Dispose();
- }
- public override object Target
- {
- get { return _proxy.Target; }
- }
- public override void Dispose()
- {
- if (_proxy != null)
- {
- _proxy.Dispose();
- _proxy = null;
- }
- }
- private class Proxy : IDisposable
- {
- public bool Disposed;
- public TTarget Target;
- public WeakReference Callback;
- public Action<TTarget, THandler> Add;
- public Action<TTarget, THandler> Remove;
- public THandler Handler;
- public Proxy(TTarget target, THandler callback, Action<TTarget, THandler> add, Action<TTarget, THandler> remove)
- {
- Disposed = false;
- Target = target;
- Callback = new WeakReference(callback);
- Add = add;
- Remove = remove;
- Handler = _createHandler(this);
- Add(Target, Handler);
- }
- public void Dispose()
- {
- if (!Disposed)
- {
- Remove(Target, Handler);
- Disposed = true;
- }
- }
- }
- }
- public static class EventHandleExtensions
- {
- public static EventHandle SubscribeCollectionChanged(this INotifyCollectionChanged target, NotifyCollectionChangedEventHandler callback)
- {
- return EventHandle.Create(
- target,
- callback,
- (t, h) => t.CollectionChanged += h,
- (t, h) => t.CollectionChanged -= h);
- }
- public static EventHandle SubscribePropertyChanged(this INotifyPropertyChanged target, PropertyChangedEventHandler callback)
- {
- return EventHandle.Create(
- target,
- callback,
- (t, h) => t.PropertyChanged += h,
- (t, h) => t.PropertyChanged -= h);
- }
- public static EventHandle SubscribePropertyChanged(this INotifyPropertyChanged target, PropertyChangedEventHandler callback, string propertyName)
- {
- return target.SubscribePropertyChanged((s, e) =>
- {
- if (string.IsNullOrEmpty(e.PropertyName) || e.PropertyName == propertyName)
- {
- callback(s, e);
- }
- });
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement