log4net 自定义追加器依赖项

本文关键字:依赖 追加 自定义 log4net | 更新日期: 2023-09-27 17:55:39

我要实现一个log4net自定义追加器。我的追加器工作正常,但在重新制造期间,我想隔离责任,所以我需要注入一个接口。我写了一些代码,以便您理解

namespace WebServiceLogger.Interfaces
{
    public interface IClientService
    {
        void SendLog(string logToSend);
    }
}

这是我的追加器,现在通过邮件发送日志,但是明天我想使用相同的追加器将日志发送到 Web 服务。

using log4net.Appender;
using log4net.Core;
using WebServiceLogger.Interfaces;
namespace WebServiceLogger
{
    public class WebServiceLogAppender : AppenderSkeleton
    {
        private IClientService _clientService;
        //Url property is declared with tag in my log4net.config tag
        public string Url { get; set; }     
        public WebServiceLogAppender()
        {
            InitializeClientService(); 
        }
        protected override void Append(LoggingEvent loggingEvent)
        {
            var log = RenderLoggingEvent(loggingEvent);
            _clientService.SendLog(log);
        }
        private void InitializeClientService()
        {
            var smtpClientFactory = new SmtpClientFactory();
            var mailMessageFactory = new MailMessageFactory();
            _clientService = new EmailClientService(smtpClientFactory,mailMessageFactory)
        }
    }
}

还有一个实现IClientService的类

using System.Net.Mail;
using WebServiceLogger.Interfaces;
namespace WebServiceLogger
{
    public class EmailClientService : IClientService
    {
        private readonly SmtpClient _smtpClient;
        private readonly IMailMessageFactory _mailMessageFactory;
        public EmailClientService(ISmtpClientFactory smtpClientFactory, IMailMessageFactory mailMessageFactory)
        {
            _smtpClient = smtpClientFactory.Create("username", "password");
            _mailMessageFactory = mailMessageFactory;
        }
        public void SendLog(string logToSend)
        {
            var message = _mailMessageFactory.CreateMailMessage(logToSend);
            _smtpClient.Send(message);
        }
    }
}

我不想在此类中连接 Web 服务,但我只有一个无参数构造函数。

答案是,我可以在log4net.config中指定一个实现IClientService接口的类的对象吗?

log4net 自定义追加器依赖项

因为 log4net 自己创建追加器,所以无法使用构造函数或属性注入,也不能在配置中指定类:如果你真的想在配置中指定实现IClientService的类的名称并在运行时创建它,你可以这样做,但这并不可取。

如果您的目的是减少代码重复,那么为自定义记录器创建一个基类就可以做到这一点:然后,您可以混合和匹配配置文件中的追加器。

public abstract class BaseWebServiceLogAppender : AppenderSkeleton
{
    protected IClientService _clientService;
    //Url property is declared with tag in my log4net.config tag
    public string Url { get; set; }
    public BaseWebServiceLogAppender()
    {
        InitializeClientService();
    }
    protected override void Append(LoggingEvent loggingEvent)
    {
        var log = RenderLoggingEvent(loggingEvent);
        _clientService.SendLog(log);
    }
    protected abstract void InitializeClientService();
}
public class EmailWebServiceLogAppender : BaseWebServiceLogAppender
{
    protected override void InitializeClientService()
    {
        var smtpClientFactory = new SmtpClientFactory();
        var mailMessageFactory = new MailMessageFactory();
        _clientService = new EmailClientService(smtpClientFactory,mailMessageFactory)
    }
}
public class SmsWebServiceLogAppender : BaseWebServiceLogAppender
{
    protected override void InitializeClientService()
    {
        _clientService = new SmSClientService(…);
    }
}

不确定您使用的是哪个容器。就我而言,我使用的是 Unity,并且能够在创建容器后通过容器运行追加器实例:

ILog logger = LogManager.GetLogger("My Logger");
IAppender[] appenders = logger.Logger.Repository.GetAppenders();
foreach (IAppender appender in appenders)
{
    container.BuildUp(appender.GetType(), appender);
}
container.RegisterInstance(logger);

BuildUp()方法将填充追加器类中的注入属性:

public class LogDatabaseSaverAppender : AppenderSkeleton
{
    [Dependency]
    public IContextCreator ContextCreator { get; set; }
    ...
}