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)
.NET Framework | Návrhové vzory