view Implab/Diagnostics/ListenerBase.cs @ 187:dd4a3590f9c6 ref20160224

Reworked cancelation handling, if the cancel handler isn't specified the OperationCanceledException will be handled by the error handler Any unhandled OperationCanceledException will cause the promise cancelation
author cin
date Tue, 19 Apr 2016 17:35:20 +0300
parents 240aa6994018
children d45bdf510514
line wrap: on
line source

using System;
using System.Collections.Generic;
using Implab.Components;

namespace Implab.Diagnostics {
    public abstract class ListenerBase : ServiceLocator, ILogWriter<object>, ILogWriter<TraceEvent> {

        readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();

        protected ListenerBase() {
            Register(this);
        }

        public void Subscribe(Type eventType) {
            if (eventType == null)
                throw new ArgumentNullException("eventType");
            GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
        }

        public void Subscribe<TEvent>() {
            Subscribe<TEvent>(LogChannel<TEvent>.Default);
        }

        public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
            if (channel == null)
                throw new ArgumentNullException("channel");

            lock (m_subscriptions) {
                AssertNotDisposed();
                if (m_subscriptions.ContainsKey(channel))
                    return;

                var writer = GetService<ILogWriter<TEvent>>();

                EventHandler<LogEventArgs<TEvent>> handler = (sender, args) => writer.Write(args,args.Value);

                channel.Events += handler;

                Action unsubscribe = () => {
                    channel.Events -= handler;
                };

                m_subscriptions.Add(channel, unsubscribe);
            }
        }

        public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
            if (channel == null)
                throw new ArgumentNullException("channel");

            lock (m_subscriptions) {
                Action subscription;
                if (m_subscriptions.TryGetValue(channel, out subscription)) {
                    subscription();
                    m_subscriptions.Remove(channel);
                }
            }
        }

        public void UnsubscribeAll() {
            lock (m_subscriptions) {
                foreach (var subscription in m_subscriptions.Values)
                    subscription();
                m_subscriptions.Clear();
            }
        }

        #region ILogWriter implementation
        public abstract void Write(LogEventArgs args, object entry);
        #endregion

        #region ILogWriter implementation
        public virtual void Write(LogEventArgs args, TraceEvent entry) {
            Write(args, (object)entry);
        }
        #endregion


        protected override void Dispose(bool disposing) {
            base.Dispose(disposing);
            if (disposing) {
                UnsubscribeAll();
            }
        }
    }
}