Вопрос по .net, log4net, c#-4.0 – Как я могу использовать log4net для входа в RichTextBox?

3

Я хотел бы видеть записи log4net, показанные в Windows.Forms.RichTextBox. Я думал об использовании MemoryAppender, но я не уверен, как получить запись каждый раз, когда она добавляется как событие.

Взгляните на этот пост SO - он включает в себя текстовое поле, но с той же разницей (обратите внимание, что они используют таймер для добавления событий):stackoverflow.com/questions/10950779/... pstrjds

Ваш Ответ

1   ответ
7

log4net по сути, это push-модель, которая неочевидна (большинство людей связывают вызовы методов с pull-моделями), но мы можем изменить ее на другую push-модель, с которой большинство разработчиков .NET более знакомы (события), и построить другую push-модель поверх то, что облегчает нам подписку / отписку на эти события (наблюдаемые).

Что вам нужно сделать, это создать реализациюIAppender интерфейс и переводить вызовы реализации интерфейса в события.

Позволять'определитьEventArgs класс, который тыбудем использовать, чтобы указать, что событие имело место:

public class LogEventArgs : EventArgs
{
    public LogEventArgs(IEnumerable<loggingevent> loggingEvents)
    {
        // Validate parameters.
        if (loggingEvents == null) 
            throw new ArgumentNullException("loggingEvents");

        // Assign values.
        LoggingEvents = loggingEvents;
    }

    // Poor-man's immutability.
    public IEnumerable<loggingevent> LoggingEvents { get; private set; }
}
</loggingevent></loggingevent>

Следует отметить, что это разоблачает последовательностьLoggingEvent случаи, так как мы хотим поддержатьIBulkAppender интерфейс также.

С этим из пути мы можем создать реализациюIAppender, Обратите внимание, что есть толькодва метода что вы должны реализовать. Более важный из двухDoAppend где тыПереведу звонок в событие:

public class EventAppender : AppenderSkeleton
{
    // Note, you will probably have to override other things here.

    // The lock for the event.
    private readonly object _eventLock = new object();

    // The backing field for the event.
    private EventHandler<logeventargs> _loggedEventHandlers;

    // Add and remove methods.
    public event Logged
    {
        add { lock(_eventLock) _loggedEventHandlers += value; }
        remove { lock(_eventLock) _loggedEventHandlers -= value; }
    }

    // Singular case.
    protected override void Append(LoggingEvent loggingEvent)
    {
        // Validate parameters.
        if (loggingEvent == null) 
            throw new ArgumentNullException("loggingEvent");

        // Call the override that processes these in bulk.
        Append(new [] { loggingEvent });
    }

    // Multiple case.
    protected override void Append(LoggingEvent[] loggingEvents)
    {
        // Validate parameters.
        if (loggingEvents == null)
            throw new ArgumentNullException("loggingEvents");

        // The event handlers.
        EventHandler<logeventargs> handlers;

        // Get the handlers.
        lock (_eventLock) handlers = _loggedEventHandlers;

        // Fire if not null.
        if (handlers != null) handlers(new LogEventArgs(loggingEvents);
    }
}
</logeventargs></logeventargs>

Если у вас есть это, вы можетепрограммно добавить приложение, Это'Вероятно, это проще сделать программно, так как это облегчает поиск экземпляра, к которому нужно присоединить событие. Тем не мение,Вы можете пройтись по списку претендентов, чтобы найти его если это'ваши предпочтения.

Затем это'Это всего лишь вопрос передачи события из этого экземпляра в обработчик, который будет писать в.RichTextBox

Если у вас есть это, вы можете легко превратить это вIObservable реализации, и сгладить всеLoggingEvent экземпляров.

Ты первый'взять класс выше, и создатьIObservable с использованиемObservable.FromEvent метод:

// The appender that was added programmatically.
EventAppender appender = ...;

// Get the observable of LogEventArgs first.
IObservable<logeventargs> logEventObservable = 
    Observable.FromEvent<logeventargs>(
        a => appender.Logged += a, a => appender.Logged -= a);
</logeventargs></logeventargs>

На данный момент, однако, мы хотим немного упростить обработку отдельных экземпляровLoggingEvent учебный класс. Там'нет причинваш код должен сделать это. Это легко сделать с помощьюSelectMany метод расширения:

// The observable of the individual LoggingEvent instances.
IObservable<loggingevent> loggingEvents = logEventObservable.
    SelectMany(e => e.LoggingEvents);
</loggingevent>

Оттуда вы можете легко подписаться наIObservable экземпляр для публикации в потоке пользовательского интерфейса при появлении новых событий:

// The RichTextBox.
RichTextBox rtb = ...;

// This code goes where you want to start subscribing.  This needs to be
// called on the UI thread, because you need the proper
// SynchronizationContext:
IObservable<loggingevent> synchronized = loggingEvents.ObserveOn(
    SynchronizationContext.Current);

// Subscribe to the event.  Store the result of this.
IDisposable unsubscribe = synchronized.
    // If you need to do anything fancier, then use the
    // LoggingEvent represented in e and update the
    // RichTextBox accordingly.
    Subscribe(e => rtb.AppendText(e.RenderedMessage));
</loggingevent>

Затем, если вы хотите отказаться от подписки (прекратить получать обновления), вы просто позвонитеDispose метод наIDisposable реализация вернулась из вызова к.Subscribe

Некоторые из преимуществ использованияIObservable вот:

Маршаллинг обратного вызова в потоке пользовательского интерфейса обрабатывается для васObserveOn метод.Вы можете фильтровать / преобразовывать / и т.д. последовательности с использованием методов расширения вSystem.Reactive.Linq Пространство именв частности, методы расширения наObservable учебный класс которые позволяют использоватьвыражения запросов в C #.Расширения дляIObservable реализации позволяют вам делать такие вещи, как буферизация (если выполучаюпуть слишком много сообщений одновременно), раздвижные окна и т. д.Вы можете легко объединить этот поток событий с другими потоками событий.
Ты неиметь" подписаться программно ... вы можете пройтись по списку претендентов и найти его :) У вас еще есть +1 за это. Я хотел бы поднять голосование дальше, так как это очень тщательно. pstrjds

Похожие вопросы