\


 Sunday, 26 September 2004
Logování událostí v mediátoru

V mediátoru, kterého jsem popisoval v jednom dřívějším spotu, potřebujeme při testování logovat všechny příchozí události, které jsou předdefinovaným a bezpečným způsobem distribuovány dalším objektům. Nejméně náročnou cestou na napsání, volenou většinou vývojáři, kteří se pravděpodobně do IT rekrutují z rekvalifikovaných potomků nejzarytějších stachanovců;), je logování každé události zvláštní metodou. Po registaci nových událostí do mediátora je vždy i změněna komponenta pro logování, takže o údržbě takového kódu si můžete nechat zdát jen mrazivé sny o opětovném plíživém nahrazování kvality kvantitou.*

Na údržbu nenáročné a univerzální řešení spočívá ve vytvoření preprocesoru (viz spot o mediátoru), který je vyvolán před distribucí událostí ostatním objektům a který parametry události vypíše přes objekt Trace z jmenného prostoru System.Diagnostics.

Základní myšlenky v preprocesoru.

1) Většina (ne li každý) objekt v business vrstvě má unikátní identifikátor s názvem Id. Preprocesor události vypíše typ objektu, který událost vyvolal a jeho unikátní Id, takže je snadné dohledat zdroj problematických událostí.

2) Objekty nesoucí parametry událostí dědí vždy z třídy EventArgs. Přes reflection vypíšeme rekurzívně hodnoty vlastností do úrovně nastavené ve vlastnosti EndDumpLevel.

using System;
using System.Diagnostics;
using System.Reflection;
namespace RStein.Utilities
{
    /// <summary>
    ///  Třída EventsLog pro logování událostí
    /// </summary>
    public class EventsLog
    {
       
        #region private constants
        private const int BEGIN_DUMP_LEVEL = 1;
        private const int DEFAULT_END_DUMP_LEVEL = 2;
        #endregion private constants
        #region private variables
        private int m_endLevel;
        #endregion private variables
        #region Constructors
        /// <summary>
        /// Konstruktor
        /// </summary>
        public EventsLog() : base()
        {
            m_endLevel = DEFAULT_END_DUMP_LEVEL;
        }
        #endregion Constructors
        #region Public properties
        /// <summary>
        /// Koncová úroveň rekurzivního výpisu vlastností objeudálosti
        /// </summary>
        public int EndDumpLevel
        {
            get
            {
                return m_endLevel;
               
            }
            set
            {
                if (value < 1)
                    throw new ArgumentOutOfRangeException("Value must be greater than 1");
                
                m_endLevel = value;   
            }
           
        }
        #endregion Public properties
        #region Public methods
       
        /// <summary>
        /// Metoda pro výpis informace o událostech
        /// </summary>
        /// <param name="sender">Zdroj události</param>
        /// <param name="e">Parametry události</param>
        public void ProcessEvent(object sender, EventArgs e)
        {   
            Debug.Assert((sender != null) && (e != null), "EventsLog - Invalid event data");
           
            if ((sender == null)||
                (e == null))
            {
                    return;
            }
               
           
                Trace.WriteLine(new string('-',25));
                dumpId(sender);
                dumpEventProperties(e);
           
        }
        #endregion Public methods
        #region Private methods
       
        //Zapsání Id a názvu objektu
        private void dumpId (object sender)
        {
           
            Type senderType = sender.GetType();
            PropertyInfo idInfo = senderType.GetProperty("Id");
            string id = String.Empty;
           
            if (idInfo != null)
                id = idInfo.GetValue(sender, null).ToString();
            Trace.WriteLine(String.Format("Přijata událost od objektu {0}, Id = {1}", senderType.ToString(), id));
        }
        //Vypsani vlastností objektu s parametry události
        private void dumpEventProperties(EventArgs e)
        {
           
            Type eventType = e.GetType();
            Trace.WriteLine(String.Format("Objekt události -  {0}", eventType.ToString()));
            PropertyInfo[] eventInfo = eventType.GetProperties();
            Trace.WriteLine("Výpis hodnot událostí");
            writeEventValues(eventInfo, BEGIN_DUMP_LEVEL, e);
        }
        //Metoda pro rekurzivní výpis hodnot vlatností
        private void writeEventValues(PropertyInfo[] eventInfo, int level, object o)
        {
            foreach (PropertyInfo info in eventInfo)
            {
               
               
                //Nezpracovávat indexované vlastnosti
                if (info.GetIndexParameters().Length != 0)
                    continue;
               
                object propValue = info.GetValue(o, null);
               
               
                if (propValue == null)
                    continue;
               
                Trace.Write(new String('\t', level));
                Trace.WriteLine(String.Format("Jméno - {0}, Hodnota = {1}", info.Name, propValue.ToString()));
               
                if (level < EndDumpLevel)
                    writeEventValues(propValue.GetType().GetProperties(), level + 1, propValue);
            }
        }
       
        #endregion Private methods
    }
}
 
 
*Pozorný čtenář z tohoto spotu dokáže vyčíst i mou politickou orientaci a nechuť k určitému druhu myšlení;)



Sunday, 26 September 2004 17:02:00 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | Návrhové vzory