.net - 如何使用 log4net 登录 RichTextBox?

标签 .net c#-4.0 log4net

我希望看到 Windows.Forms.RichTextBox 中显示的 log4net 条目。我正在考虑使用 MemoryAppender,但我不确定每次将其添加为事件时如何获取该条目。

最佳答案

log4net本质上是一个推模型,这一点并不明显(大多数人将方法调用与拉模型联系起来),但我们可以将其更改为大多数.NET开发人员更熟悉的另一种推模型(事件),并在其之上构建另一个推模型这使我们更容易订阅/取消订阅这些事件(可观察对象)。

您需要做的是创建 IAppender interface 的实现并将对接口(interface)实现的调用转换为事件。

让我们定义 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 的序列实例,因为我们要支持 IBulkAppender interface

除此之外,我们可以创建 IAppender 的实现.请注意,只有 two methods你必须实现。两者中比较重要的是 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);
    }
}

一旦有了这个,您就可以 programmatically append the appender .以编程方式执行此操作可能更容易,因为它有助于找到要将事件附加到的实例。然而,you can walk the list of appenders to find it如果这是您的偏好。

然后,只需将事件从该实例连接到将写入 RichTextBox 的处理程序即可。 .

一旦你有了这个,你就可以很容易地将它变成一个 IObservable<T> 实现,并展平所有 LoggingEvent实例。

首先,您将学习上面的类(class),并创建一个 IObservable<LogEventArgs>使用 Observable.FromEvent method :

// 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);

虽然在这一点上,我们想让处理 LoggingEvent 的单个实例变得更容易一些。类(class)。 您的 代码没有理由必须这样做。这可以很容易地用 SelectMany extension method 完成。 :

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

从那里,您可以轻松订阅 IObservable<LoggingEvent>当新事件进入时发布到 UI 线程的实例:

// 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));

然后,如果您想取消订阅(停止接收更新),您只需调用 Dispose method IDisposable 上从对 Subscribe 的调用返回的实现.

使用 IObservable<T> 的一些优势这里是:

  • 返回 UI 线程的回调由 ObserveOn 为您处理。方法。
  • 您可以过滤/转换/等等。使用 System.Reactive.Linq namespace 中的扩展方法的序列,特别是 Observable class 上的扩展方法允许使用 query expressions in C# .
  • IObservable<T> 的扩展名实现允许您执行诸如缓冲(如果您方式一次收到太多消息)、滑动窗口等操作。
  • 您可以轻松地将此事件流与其他事件流结合起来。

关于.net - 如何使用 log4net 登录 RichTextBox?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13420929/

相关文章:

.net - 有Windows Azure本地开发环境吗?

c# - 是否有人发布了任何 C# 4 编码标准/指南/风格指南?

visual-studio-2010 - Vs2010 使用 log4net 和 Intellisense

c# - Log4Net smtp appender 仅在出现完整日志(调试和信息和错误)错误时发送电子邮件。仅当应用程序结束时

c# - datagridview单元格鼠标悬停背景色更改

.net - dotNet 2.0 中哪种 FIPS 兼容算法更好?

c# - 在编译时不知道目标类型的情况下设置属性

c# - 反射(reflection)动态类型以判断它是否是动态类型,首先

ASP.NET MVC(二)log4net日志记录模式

.net - 如何自定义 PropertyGrid 上的类别排序?