I'm going to implement a log4net custom appender. My appender work fine but during refactory i want isolate the responsability, so i need to inject one interface. I write some code so you can understand
namespace WebServiceLogger.Interfaces
{
public interface IClientService
{
void SendLog(string logToSend);
}
}
This is my Appender that now send log by mail, but tomorrow i want use the same appender for send log to a web service.
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)
}
}
}
And one class that implement 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);
}
}
}
I don't want cable the webservice inside this class but i have only a parameterless constructor.
The answer is , can i specify the object of one class that implement the IClientService interface in log4net.config ?
Because log4net creates the appenders itself, it isn't possible to use constructor or property injection, and you cannot specify a class in the config: you could if you really wanted to just specify the name of the class implementing
IClientService
in the config and create it at runtime, but that's not really advisable.If your intention is to reduce code duplication, then creating a base class for your custom logger will do that: then you can mix and match the appenders in your config file.