是否可以创建具有通用事件的类?

时间:2014-10-29 16:53:17

标签: c# generics event-handling

public sealed class WeakEvent<TDelegate>
{
        public event TDelegate OnEvent;

     ...
     ...
}

我刚创建了自定义的WeakEventHandler,我想将它包装在WeakEvent类中

我不确定是否有一个好主意

    private HashSet<TDelegate> _eventHandlerList = new HashSet<TDelegate>();

并手动调用所有方法。

如果你想看到WeakEventHandler:

  public sealed class WeakEventHandler2<TDelegate>
    {
        private readonly WeakReference _targetRef;
        private readonly Action<WeakEventHandler2<TDelegate>> _unsubscriber;
        private readonly TDelegate _realHandler;
        private readonly MethodInfo _subscriberMethodInfo;

        static WeakEventHandler2()
        {
            if (!typeof(TDelegate).IsSubclassOf(typeof(Delegate)))
                throw new InvalidOperationException(typeof(TDelegate).Name + " is not a delegate type");
        }

        public WeakEventHandler2(TDelegate subscriber, Action<WeakEventHandler2<TDelegate>> unsubscriber)
        {
            var handler = (subscriber as Delegate);
            if (handler == null)
            {
                throw  new InvalidOperationException("subscriber is not a Delegate");
            }

            _unsubscriber = unsubscriber;
            _targetRef = new WeakReference(handler.Target);
            _subscriberMethodInfo = handler.Method;

            //Delegate Parameters
            ParameterExpression[] parameters =
                _subscriberMethodInfo.GetParameters()
                    .Select(parameter => Expression.Parameter(parameter.ParameterType, parameter.Name))
                    .ToArray();

            //Target instance ( holded by the weak reference
            ParameterExpression target = Expression.Parameter(typeof(object), "target");

            //call to the subscriber on a specific  target instance
            LambdaExpression methodCall  =
                Expression.Lambda(
                    Expression.Call(Expression.Convert(target, handler.Target.GetType()), handler.Method, parameters),
                    new[] {target}.Concat(parameters));

            //Expression of weakreference target
            Expression<Func<object>> instanceExpr = () => _targetRef.Target;
            //Expression of unsubscribing call
            Expression<Action> unsubscriberExpr = () => _unsubscriber(this);

            ParameterExpression tExp = Expression.Variable(typeof (object),"instanceVarContainer");
            BinaryExpression assignement = Expression.Assign(tExp, Expression.Invoke(instanceExpr));
            ConditionalExpression body = Expression.IfThenElse(Expression.NotEqual(tExp, Expression.Constant(null, typeof (object))),
                Expression.Invoke(methodCall, new[] { tExp }.Concat(parameters)), Expression.Invoke(unsubscriberExpr));

            //call to the subscriber with unsubscription in case the weakreference is not alive
            _realHandler = Expression.Lambda<TDelegate>(Expression.Block(new[] { tExp }, assignement, body), parameters).Compile();

        }

        public static implicit operator TDelegate(WeakEventHandler2<TDelegate> weh)
        {
            return weh._realHandler;
        }


    }

1 个答案:

答案 0 :(得分:0)

好吧如果有人想知道,它会是这样的:

 public class WeakEvent2<TDelegate> where TDelegate : class
 {

        private TDelegate _invocationList;

         public TDelegate Invoke
        {
            get { return _invocationList;    }
        }


        public void Subscribe(TDelegate handler)
        {
            lock (this)
                _invocationList = Delegate.Combine(_invocationList as Delegate, new WeakEventHandler2(handler, weh=> Unsubscribe(weh) )) as TDelegate;
        }

        ...
        ...
}
相关问题