File: UI\RenderTraceListener.cs
Project: ndp\fx\src\xsp\system\Web\System.Web.csproj (System.Web)
//------------------------------------------------------------------------------
// <copyright file="RenderTraceListener.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
 
namespace System.Web.UI {
 
    using System.Collections.Generic;
    using System.IO;
 
    /// <summary>
    /// Abstract base class for an object that wants to be notified as controls
    /// are rendering during a page request.
    /// </summary>
    public abstract class RenderTraceListener {
        private static readonly RenderTraceListener _nullListener = new NullRenderTraceListener();
 
        private static List<Func<RenderTraceListener>> _factories;
 
        /// <summary>
        /// Functions added to this list are called to instantiate RenderTraceListeners
        /// for each request.
        /// </summary>
        public static IList<Func<RenderTraceListener>> ListenerFactories {
            get {
                if (_factories == null) {
                    _factories = new List<Func<RenderTraceListener>>();
                }
                return _factories;
            }
        }
 
        internal static RenderTraceListener CurrentListeners {
            get {
                if (_factories != null && HttpContext.Current != null) {
                    RenderTraceListener listener = HttpContext.Current.Items[typeof(RenderTraceListener)] as RenderTraceListener;
                    if (listener == null) {
                        listener = CreateListener(HttpContext.Current);
                        HttpContext.Current.Items[typeof(RenderTraceListener)] = listener;
                    }
                    return listener;
                }
 
                return _nullListener;
            }
        }
 
        private static RenderTraceListener CreateListener(HttpContext context) {
            List<RenderTraceListener> listeners = new List<RenderTraceListener>();
 
            foreach (Func<RenderTraceListener> factory in _factories) {
                RenderTraceListener listener = factory();
 
                if (listener != null) {
                    listeners.Add(listener);
                }
            }
 
            RenderTraceListenerList list = new RenderTraceListenerList(listeners);
 
            list.Initialize(context);
 
            return list;
        }
 
        /// <summary>
        /// Called to initialize the listener.
        /// </summary>
        public virtual void Initialize(HttpContext context) {
        }
 
        /// <summary>
        /// Called to associate a data object with a Control or other object
        /// that will be rendered.
        /// </summary>
        public virtual void SetTraceData(object tracedObject, object traceDataKey, object traceDataValue) {
        }
 
        /// <summary>
        /// Called to associate the trace data from one object with another object.
        /// </summary>
        public virtual void ShareTraceData(object source, object destination) {
        }
 
        /// <summary>
        /// Called when an object is about to be rendered.
        /// </summary>
        public virtual void BeginRendering(TextWriter writer, object renderedObject) {
        }
 
        /// <summary>
        /// Called when an object is finished rendering.
        /// </summary>
        public virtual void EndRendering(TextWriter writer, object renderedObject) {
        }
 
        private sealed class NullRenderTraceListener : RenderTraceListener {
        }
 
        private sealed class RenderTraceListenerList : RenderTraceListener {
            private readonly List<RenderTraceListener> _listeners;
 
            internal RenderTraceListenerList(List<RenderTraceListener> listeners) {
                _listeners = listeners;
            }
 
            public override void Initialize(HttpContext context) {
                foreach (RenderTraceListener listener in _listeners) {
                    listener.Initialize(context);
                }
            }
 
            public override void SetTraceData(object tracedObject, object traceDataKey, object traceDataValue) {
                foreach (RenderTraceListener listener in _listeners) {
                    listener.SetTraceData(tracedObject, traceDataKey, traceDataValue);
                }
            }
 
            public override void ShareTraceData(object source, object destination) {
                foreach (RenderTraceListener listener in _listeners) {
                    listener.ShareTraceData(source, destination);
                }
            }
 
            public override void BeginRendering(TextWriter writer, object renderedObject) {
                foreach (RenderTraceListener listener in _listeners) {
                    listener.BeginRendering(writer, renderedObject);
                }
            }
 
            public override void EndRendering(TextWriter writer, object renderedObject) {
                // Call EndRendering in the reverse order from BeginRendering,
                // so that listeners are called in a nested fashion
                for (int i = _listeners.Count - 1; i >= 0; i--) {
                    _listeners[i].EndRendering(writer, renderedObject);
                }
            }
        }
    }
}