Добавить методы трассировки в System.Diagnostics.TraceListener

Я написал класс Log, производный от System.Diagnostics.TraceListener, вот так

public class Log : TraceListener

Это действует как оболочка для Log4Net и позволяет людям использовать System.Diagnostics Tracing примерно так

Trace.Listeners.Clear();
Trace.Listeners.Add(new Log("MyProgram"));
Trace.TraceInformation("Program Starting");

Есть запрос на добавление дополнительных уровней трассировки, чем уровни трассировки по умолчанию (Ошибка, Предупреждение, Информация)

Я хочу добавить это в System.Diagnostics.Trace, чтобы его можно было использовать как

Trace.TraceVerbose("blah blah");
Trace.TraceAlert("Alert!");

Есть ли способ сделать это с помощью класса расширения? Я старался

public static class TraceListenerExtensions
{
     public static void TraceVerbose(this Trace trace) {}
}

но ничего не передается на экземпляре трассировки, передаваемом в:(

2 ответа

Решение

Это слишком поздно, но вы рассматривали возможность использования TraceSource? TraceSources предоставляет вам реальные экземпляры объектов, которые вы можете использовать для входа в System.Diagnostics (что означает, что вы можете расширять их с помощью метода расширения, как вы предлагаете в своем вопросе). TraceSources обычно настраиваются в app.config (аналогично тому, как вы настраиваете регистраторы log4net). Вы можете контролировать уровень регистрации и какие слушатели трассировки слушают. Таким образом, вы можете иметь код приложения, запрограммированный на TraceSource, который может выглядеть примерно так:

public class MyClassThatNeedsLogging
{
  private static TraceSource ts = 
          new TraceSource(MethodBase.GetCurrentMethod().DeclaringType.Name);
  //Or, to get full name (including namespace)
  private static TraceSource ts2 = 
          new TraceSource(MethodBase.GetCurrentMethod().DeclaringType.FullName);

  private count;

  public MyClassThatNeedsLogging(int count)
  {
    this.count = count;

    ts.TraceEvent(TraceEventType.Information, 0, "Inside ctor.  count = {0}", count);
  }

  public int DoSomething()
  {
    if (this.count < 0)
    {
      ts.TraceEvent(TraceEventType.Verbose, 0, "Inside DoSomething.  count < 0");
      count = Math.Abs(count);
    }

    for (int i = 0; i < count; i++)
    {
      ts.TraceEvent(TraceEventType.Verbose, 0, "looping.  i = {0}", i);
    }
  }
}

Вы также можете создать TraceSources, используя любое имя (т.е. оно не обязательно должно быть именем класса):

TraceSource ts1 = new TraceSource("InputProcessing");
TraceSource ts2 = new TraceSource("Calculations");
TraceSource ts3 = new TraceSource("OutputProcessing");

Как я упоминал ранее, каждый TraceSource обычно настраивается в файле app.config вместе с "уровнем" ведения журнала и слушателем, который должен получить выходные данные.

Для вашего метода расширения вы можете сделать что-то вроде этого:

public static class TraceSourceExtensions
{
  public static void TraceVerbose(this TraceSource ts, string message)
  {
    ts.TraceEvent(TraceEventType.Verbose, 0, message);
  }
}

Если вам нужно больше настраивать TraceSource (например, добавлять дополнительные уровни), это довольно хорошая статья, которая описывает, как это сделать:

http://msdn.microsoft.com/en-us/magazine/cc300790.aspx

Если вы в конечном итоге используете log4net внутри своего TraceListener (и используете его для определения именованных регистраторов, уровней ведения журналов и т. Д.), Вам может не потребоваться настройка многих TraceSources. Возможно, вы даже сможете настроить только один (имя которого будет хорошо известно), или вы сможете создать его программно, настроить его на запись "всего" и подключить его к вашему конкретному TraceListener.

В конце концов, вместо входа через статический объект Trace, вы можете войти через экземпляры TraceSource. Если настроен один TraceSource и его имя хорошо известно, допустимый TraceSource может быть создан (для ведения журнала) в любом месте, например так:

TraceSource ts = new TraceSource("logger");
ts.TraceEvent(TraceEventType.Information, 0, "Hello World!");
//Or, via your extension method
ts.TraceVerbose(TraceEventType.Verbose, 0, "Logged via extension method");

Могут быть и более эффективные способы выполнения того, что вы пытаетесь выполнить, но это может дать вам возможность подумать об использовании TraceSource против статического класса Trace.

Ваша проблема в том, что вы не можете добавить методы расширения для работы со статическими классами. Первый параметр метода расширения - это экземпляр, с которым он должен работать. Так как Trace класс статичен, такого экземпляра нет. Возможно, вам лучше создать свою собственную оболочку статического журнала, раскрывая методы, которые вы хотите иметь, такие как TraceVerbose:

public static class LogWrapper
{
    public static void TraceVerbose(string traceMessage)
    {
        Trace.WriteLine("VERBOSE: " + traceMessage);
    }
    // ...and so on...
}

Это также отсоединит ваш код регистрации от фактической используемой среды ведения журнала, так что вы сможете позже переключиться с ведения журнала трассировки на использование log4net или чего-то еще, если хотите.

Другие вопросы по тегам