>Ciao a tutti,
>forse sto per dire una baggianata...
>Se dovessi utilizzare il Tracelistener per monitorare un'applicazione
>che ho realizzato, devo mettere questa istruzione
>
>Trace.WriteLine("working...", "MyApp");
>
>ad ogni riga di codice?
>Scusate la domanda altrimenti non capisco.
>
Eh si, devi scrivere quella istruzione dove vuoi che venga loggata l'informazione.
Però la tua domanda non è stupida, in quanto per 20 anni se la sono posta anche altri sviluppatori, e hanno sviluppato nel tempo quella che è chiamta l'AOP (Aspect oriented programming), in pratica un modo di programmare che ti permette di innestare comportamenti ad un metodo pre-esistente, senza dovergli cambiare una riga di codice, ma mettendosi intorno allo stesso, intercettandone l'esecuzione prima che avvenga.
Quindi è possibile sviluppare un sistema che autonomamente effettui il log dell'entrate dei metodi, ne misuri la tempistica, ecc... questo in c# si può fare con un dynamic proxy, gentilmente offerto da Castle Windsor:
http://docs.castleproject.org/Windsor.Introduction-to-AOP-With-Castle.ashx
http://ayende.com/blog/3474/logging-the-aop-way
ma con il castle ovviamente devi impostare il progetto correttamente per poterlo sfruttare, devi istanziare gli oggetti per forza passando dal castle container, che poi ti permette appunto di aggiungere tutti gli Interceptor che vuoi, tra cui il tipi LoggingInterceptor.
Altrimenti se si vuole un sistema di logging senza dovere scrivere una riga di codice, e/o in generale avere un soluzione ancora più orientata all'AOP, devi passare a PostSharp, quest'ultimo invece che sfruttare i dynamic proxy, si intromette nel processo di build per iniettare codice direttamente dove deve essere eseguito: http://www.postsharp.net/
In entrambi i casi se vuoi logging dettagliato all'istruzione, internamente ad una funzione, devi scrivere quelle righe che dicevi, ma di solito diventano superflue, se sai già, come in AOP, con che parametri è chiamato un metodo è più che sufficiente, ad ogni modo sforzati di astrarre il sistema di logging, non scrivere direttamente Trace.WriteLine, log.Debug, ecc... ma sviluppa e utilizza un interfaccia in comune tipo ILogger (nel castle questa interfaccia è già presente), ti copio appunto una parte di quella del castle:
/// <summary>
/// Manages logging.
/// </summary>
/// <remarks>
/// This is a facade for the different logging subsystems.
/// It offers a simplified interface that follows IOC patterns
/// and a simplified priority/level/severity abstraction.
/// </remarks>
public interface ILogger
{
/// <summary>
/// Logs a debug message.
/// </summary>
/// <param name = "message">The message to log</param>
void Debug(String message);
/// <summary>
/// Logs an error message.
/// </summary>
/// <param name = "message">The message to log</param>
void Error(String message);
/// <summary>
/// Logs an error message.
/// </summary>
/// <param name = "message">The message to log</param>
/// <param name = "exception">The exception to log</param>
void Error(String message, Exception exception);
/// <summary>
/// Logs an info message.
/// </summary>
/// <param name = "message">The message to log</param>
void Info(String message);
/// <summary>
/// Logs a warn message.
/// </summary>
/// <param name = "message">The message to log</param>
void Warn(String message);
}
ovviamente puoi fare un interfaccia più piccola, ma il succo è quelo, poi la implementi con i vari formati, in questo modo puoi decidere se loggare su console, trace, log4net, nlog, ecc... basta una semplice implementazione come questa:
public class TraceLogger : ILogger
{
public void Debug(string message)
{
Trace.WriteLine(message);
}
public void Error(string message)
{
Trace.TraceError(message);
}
public void Error(string message, Exception exception)
{
Trace.TraceError("{0}: {1}", message, exception.ToString());
}
public void Info(string message)
{
Trace.TraceInformation(message);
}
public void Warn(string message)
{
Trace.TraceWarning(message);
}
}
public class NullLogger : ILogger
{
private static readonly ILogger _nullLogger = new NullLogger();
public static ILogger Instance
{
get { return _nullLogger; }
}
public void Debug(string message)
{
}
public void Error(string message)
{
}
public void Error(string message, Exception exception)
{
}
public void Info(string message)
{
}
public void Warn(string message)
{
}
}
e poi nel codice usi solo l'interfaccia, invece che usare direttamente Trace.WriteLine:
public class MyIncredibleClass
{
private ILogger _logger = NullLogger.Instance;
public ILogger Logger
{
get { return _logger; }
set { _logger = value; }
}
public void DoSomethingSpecial()
{
try
{
_logger.Debug("Enter DoSomethingSpecial()");
}
catch (Exception ex)
{
_logger.Error(ex.Message, ex);
}
finally
{
_logger.Debug("Exit DoSomethingSpecial()");
}
}
}
come vedi non sono più legato a nessun tipo in particolare di logging, posso passare alla mia classe qualsiasi tipo di logger mi possa venire in mente, senza poi dovere ricambiare una riga di codice, devo solo implementare un altro Logger e il gioco è fatto. Ho anche implementato un NullLogger, molto utile quando si vuole completamente disabilitare il logging, e sopratutto per rendere la tua classe non dipendente affatto da un sistema di logging, di fatto rendendolo opzionale, se non imposti la proprietà oggetto.Logger = new TraceLogger(); il log non sarà abilitato, ma il codice non darà mai errore, semplicemente eseguirà un metodo vuoto, di un oggetto statico istanziato solo una volta (static NullLogger).
Ciao!
Michael Denny | Microsoft Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.net
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic