Mercurial > pub > ImplabNet
diff Implab/Diagnostics/TextListenerBase.cs @ 40:fe33f4e02ad5
improved tracing
added text listeners (file,console)
author | cin |
---|---|
date | Tue, 15 Apr 2014 17:52:09 +0400 |
parents | |
children | 7c2369f580b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Diagnostics/TextListenerBase.cs Tue Apr 15 17:52:09 2014 +0400 @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Implab.Diagnostics { + public abstract class TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> { + + readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>(); + + protected TextListenerBase() { + 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(); + + var formatter = GetService<IEventTextFormatter<TEvent>>(); + + EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => { + WriteEntry((TraceContext)sender, formatter.Format((TraceContext)sender, args.Value)); + }; + + if (m_subscriptions.ContainsKey(channel)) + return; + + 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(); + } + } + + protected abstract void WriteEntry(TraceContext context, EventText text); + + public EventText Format(TraceContext context, object data) { + return new EventText { + indent = context.CurrentOperation.Level, + content = data.ToString() + }; + } + + public EventText Format(TraceContext context, TraceEvent data) { + var level = context.CurrentOperation.Level; + if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted) + level--; + + return new EventText { + indent = level, + content = data.ToString() + }; + } + + protected override void Dispose(bool disposing) { + if (disposing) { + UnsubscribeAll(); + } + base.Dispose(disposing); + } + } +}