2012-05-14 20 views
15

Estoy buscando una forma de agregar y eliminar un TraceListener para todos los TraceSources existentes.agregar/eliminar TraceListener a todos los TraceSources

(No estoy seguro de que mi enfoque sea correcto aquí, ¿qué otras formas podría usar? Básicamente quiero registrar todas las salidas de rastreo en un archivo que use el nombre del proyecto actual como nombre de archivo. Siempre que un usuario cree o vuelva a abrir proyecto, quiero añadir registros al archivo correcto Sólo puede haber un proyecto abierto a la vez)

Código ejemplo:..

puedo crear varios TraceSources en mi solicitud, una para cada clase

public class Class1 
{ 
    private static readonly System.Diagnostics.TraceSource trace = 
      new System.Diagnostics.TraceSource("Class1"); 
} 

public class Class2 
{ 
    private static readonly System.Diagnostics.TraceSource trace = 
      new System.Diagnostics.TraceSource("Class2"); 
} 

Ahora desea agregar o quitar un TraceListener a todos mis traceSources en tiempo de ejecución, así:

private System.Diagnostics.TextWriterTraceListener myListener; 

private onProjectOpen() 
{ 
    // user created a new project or opened an existing one 
    myListener = new System.Diagnostics.TextWriterTraceListener("log-"+projectname+".log"); 
    ALL_TRACESOURCES.Add (myListener) ; // <-- how to do this? 
} 

private onProjectClose() 
{ 
    // user closed a project 
    ALL_TRACESOURCES.Remove(myListener) ; // <-- how to do this? 
    myListener.Flush(); 
    myListener.Close(); 
    myListener.Dispose(); // <-- not sure if all this is neccessary 
} 

Hasta el momento no he encontrado ninguna manera de hacer esto sin hacer todos mis traceSources pública (que parece una mala idea) y luego enumerando todas mis clases de esta manera:

Class1.Trace.Add(myListener); 
Class2.Trace.Add(myListener); 
... 

que parece una mala elección de diseño en varios niveles.

O

Añadir todos mis TraceSources a una colección personalizada global en el constructor de cada clase (fácil de olvidar/meter la pata, y las variables globales son malas)

¿Hay una mejor manera? Básicamente estoy buscando una manera de establecer otro oyente predeterminado

Respuesta

0

En .NET 4 y superior, puede usar Lazy<> para cargar sus Fuentes Trace después de que se hayan configurado las escuchas. Consulte el siguiente programa de ejemplo de trabajo:

public static class TraceSources 
{ 
    public static TraceSource Create(string sourceName) 
    { 
     var source = new TraceSource(sourceName); 
     source.Listeners.AddRange(Trace.Listeners); 
     source.Switch.Level = SourceLevels.All; 
     return source; 
    } 
} 

public class Class1 
{ 
    private static readonly Lazy<TraceSource> trace = new 
      Lazy<TraceSource>(() => TraceSources.Create("Class1")); 

    public void DoSomething() 
    { 
     trace.Value.TraceEvent(TraceEventType.Information, 1, "Class1 speaking up"); 
    } 
} 

public class Class2 
{ 
    private static readonly Lazy<TraceSource> trace = new 
      Lazy<TraceSource>(() => TraceSources.Create("Class2")); 

    public void DoSomethingElse() 
    { 
     trace.Value.TraceEvent(TraceEventType.Information, 2, "Class2 speaking out"); 
    } 
} 

public class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      var listener = new TextWriterTraceListener(@"C:\trace.txt"); 
      Trace.Listeners.Add(listener); 

      var classOne = new Class1(); 
      var classTwo = new Class2(); 
      classOne.DoSomething(); 
      classTwo.DoSomethingElse(); 
     } 
     finally 
     { 
      Trace.Close(); 
     } 
    } 
} 
0

Acabo de encontrarme con este problema yo mismo. En mi caso, también tengo fuentes de trazas creadas en cada clase. Los oyentes que están en app.config se agregan a todas las fuentes sin problema, pero hay un oyente en particular que necesito agregar en el tiempo de ejecución. Por supuesto, esto solo funciona con la fuente de seguimiento a la que se agrega el oyente. Veo dos opciones: crear una única fuente de seguimiento y pasarla al resto de la aplicación (puaj) o tener un solo origen de seguimiento estático en una clase auxiliar a la que todo lo demás hace referencia. Así que tengo:

public class LogHelper { /// /// The trace source logger for the application. /// public static readonly TraceSource Logger = new TraceSource("FruityBlergs", SourceLevels.All); }

La clase LogHelper también establece el oyente y varios otros filtros que quedan configuradas en tiempo de ejecución. Esto me ha funcionado bien hasta ahora. Si por alguna razón una clase en particular necesita un comportamiento diferente, puede crear una fuente de rastreo en esa clase.

1

Basado en this StackOverflow answer y this answer

Aquí es una manera de hacerlo:

private static void AttachToAllTraceSources(TraceListener yourListener) 
    { 
     TraceSource ts = new TraceSource("foo"); 
     List<WeakReference> list = (List<WeakReference>)GetInstanceField(typeof(TraceSource), ts, "tracesources"); 
     foreach(var weakReference in list) 
     { 
      if(weakReference.IsAlive) 
      { 
       TraceSource source = (weakReference.Target as TraceSource); 
       if(source != null && source.Name != "foo") 
       { 
        source.Listeners.Add(yourListener); 
       } 
      } 
     } 
    } 
+0

Esto sólo se consigue TraceSources que han creado una instancia. Si hubiera una manera de hacer de esto una colección observable, entonces estaríamos cocinando con gasolina. – BozoJoe

Cuestiones relacionadas