I'm using log4net in an application for logging.
I want to avoid a discussion about implementing a logging facade, but essentially, I'm creating some classes which will allow an ILog implementation to be injected via the constructor. Eg:
abstract class MigratorBase<T> : IMigrator<T>
{
private ILog logger;
public MigratorBase(ILog logger)
{
this.logger = logger;
}
}
I also would like to provide a default constructor on the class, which if called, essentially disables logging (or logs to nothing). Instead of scattering fragments of code that check if the logger is null, such as this:
if (this.logger != null)
Log.DebugFormat("Connecting to {0}", this.href);
I thought a better way to accomplish this functionality would be to assign an implementation of ILog that was purely empty methods. I could call it a NullLog, and would look similar to this:
class NullLog : ILog
{
public void Debug(object message, Exception exception) { }
public void Debug(object message) { }
public void DebugFormat(IFormatProvider provider, string format, params object[] args) { }
...
...
}
and then in the default constructor I could assign an object of this type to the class's private member, as such:
abstract class MigratorBase<T> : IMigrator<T>
{
private ILog logger;
public MigratorBase(ILog logger)
{
this.logger = logger;
}
public MigratorBase()
{
this.logger = new NullLog();
}
}
This approach seems more object oriented to me, so I think I like it, but googling seems to reveal people suggesting that it's a bad idea to implement an interface with empty methods.
Can anyone suggest why the above might be a bad idea? Or is it in fact an ok idea?
What you describe is called the Null Object pattern. Martin Fowler coined this term and explains it thoroughly in the book Patterns of Enterprise Application Architecture.
I think this is a great pattern to remove all the if-conditions in the code to check for not null. A downside could be that you have to explain a pattern in you development team and maybe add a comment about not adding functionality inside your NullLog class. Otherwise I couldn’t find a downside with this pattern.
Related
Take the following two classes:
public class PersonA
{
private readonly ILogger<PersonA> _logger;
public PersonA() : this(new NullLogger<PersonA>())
{}
public PersonA(ILogger<PersonA> logger)
{
_logger = logger;
}
public void SomeMethod()
{
_logger.LogDebug("SomeMethod invoked");
}
}
public class PersonB
{
private readonly ILogger<PersonB>? _logger;
public PersonB(ILogger<PersonB>? logger = null)
{
_logger = logger;
}
public void SomeMethod()
{
_logger?.LogDebug("SomeMethod invoked");
}
}
The way that ILogger<T> is passed is very similar in both and both approaches work, but is there any reason why you'd favour ILogger<T>? defaulting to null over two ctors one defaulting to NullLogger<T> and ensuring that _logger is never null or vice-versa?
Are any differences in performance?
As pointed out by one comment, there is so little difference in tearms of performance and object allocation that I would actually avoid to compare these two approaches in tearms of performance.
I would instead suggest the following considerations:
having two constructors is worst in terms of design. That will make creating your object harder, because the object creator has to choose between the two and have to understand the different semantic. It is much better having one and only one way to create an object: that's simpler and there is no ambiguity about the way the object should be created
as long as possible I would avoid handling null values. Code using objects that can potentially be null is harder to maintain, because if you accidentally forget the ? operator when you refactor your code you will get a NullReferenceException at runtime. You would need to write and maintain additional unit tests for the null case, in order to be sure you didn't forget a ? somewhere in your code.
Based on these two points, a better design is the following:
have a class with only one constructor
do not allow the _logger field to be nullable, that is it's type should be ILogger<Person> instead of ILogger<Person>?. In cases when you don't care about logging, use the null object pattern and inject an instance of NullLogger<Person> in the constructor (instead of using a null reference).
As a final note do not instantiate NullLogger<T>. Use, instead, the NullLogger<T>.Instance static field. By doing so, you will access to a shared cached instance of the class and you will avoid to allocate a new object (it's fine to do so for stateless classes like NullLogger<T>). This is good in tearms of memory usage and garbage collector pressure.
Final design of the class is the following:
public class Person
{
private readonly ILogger<Person> _logger;
public Person(ILogger<Person> logger)
{
// guard against null
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void SomeMethod()
{
_logger.LogDebug("SomeMethod invoked");
}
}
// if you don't care about logging
var person = new Person(NullLogger<Person>.Instance);
How do I log everywhere in the program, without having to declare ILogger parameter in every class? I would like best practice to log everywhere within program.
MyClass(ILogger<MyClass> logger)
{
_logger = logger;
}
Should I utilize a static class as described here?
public class ApplicationLogging
{
private static ILoggerFactory _Factory = null;
public static void ConfigureLogger(ILoggerFactory factory)
{
factory.AddDebug(LogLevel.None).AddStackify();
factory.AddFile("logFileFromHelper.log"); //serilog file extension
}
public static ILoggerFactory LoggerFactory
{
get
{
if (_Factory == null)
{
_Factory = new LoggerFactory();
ConfigureLogger(_Factory);
}
return _Factory;
}
set { _Factory = value; }
}
public static ILogger CreateLogger() => LoggerFactory.CreateLogger();
}
I think it's not a good idea to use a logger a static dependency. Personally, I would inject it in the constructor of the class. Why? Well, static dependencies in form of a static property have the following problems:
In the case of unit tests, they are hard to mock. If you inject the logger in the CTOR you can libs like Moq to change the logging to e.g. stdout (ok, that's also possible with e.g. log4net's config file).
Using static properties can make your code "non-determistic". Why? A static property is initialized when the class is referenced the first time. So if you change your code the static property initialization may be called earlier or later. If you've a bug in the initialization it will be hard to find. Why? Because you've no logging.
If you want to change the logging framework, you've to find all static references to it. Ok, that's not a that hard task with grep or modern IDEs. However, if you inject the logger dependency the compiler will show (based on the compile errors) which lines of code you've to change (simply remove the logger reference from the solution file).
Hope that helps.
I have a class named MyClass, which uses two different loggers named Logger1 and Logger2. I use log4net for logging, and want to use StructureMap for DI.
Without StructureMap, my class would look like this:
public class MyClass
{
private static readonly ILog Logger1 = LogManager.GetLogger("Logger1"); // Loggers are configured in a config file
private static readonly ILog Logger2 = LogManager.GetLogger("Logger2");
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
Introducing DI, with StructureMap (using v3.0.3), I would make the loggers instance members, and inject them into the constructor, like this:
public class MyClass
{
private readonly ILog Logger1;
private readonly ILog Logger2;
myClass(ILog logger1, ILog logger2)
{
this.Logger1 = logger1;
this.Logger2 = logger2;
}
public void DoSomething()
{
...
Logger1.Info("did something");
...
Logger2.Info("need to log this elsewhere");
}
}
The thing is, I cannot get StructureMap to wire this up for me properly. I tried wiring the loggers like this:
For<ILog>.Use(()=> LogManager.GetLogger("Logger1")).Named("Logger1");
For<ILog>.Use(()=> LogManager.GetLogger("Logger2")).Named("Logger2");
Doing this Gets me empty (unconfigured) loggers). Replacing Use() with Add() gives my an exception due to not having a default instance registered for ILog.
Does anybody know how I can do this?
If the loggers perform different roles then I would create two interfaces inheriting from ILog to reflect this. That way you would have no problem configuring StructureMap to handle them.
I ended up doing the following: I created two interfaces as per Rob's advice: ILogger1 and ILogger2. Since the both have the same API, as I need the same kind of functionality from them, they both inherit from the same interface - though not log4net.ILog as per Steven's advice:
interface IMyLog
{
void Info(object message);
void Info(string format, params object[] args);
}
interface ILogger1 : IMyLog { }
interface ILogger2 : IMyLog { }
Also, since the implementation of this API is the same for my needs, I have one concrete class MyLogger, implementing both ILogger1 and ILogger2. If I ever need the implementations to be different it will be easy for me to have explicit interface implementation, or separate classes. Only My Logger takes a dependency on log4net, as it uses it for its implementation:
enum LoggerType { Logger1, Logger2 }
internal class MyLogger : ILogger1, ILogger2
{
private readonly ILog _log;
public MyLogger(LoggerType loggerName)
{
switch (loggerName)
{
case LoggerType.Logger1:
_log = LogManager.GetLogger("first-log");
break;
case LoggerType.Logger2:
_log = LogManager.GetLogger("second-log");
break;
default:
throw new ArgumentException("Invalid logger name", "loggerName");
}
}
public void Info(object message)
{
_log.Info(message);
}
public void Info(string format, params object[] args)
{
_log.InfoFormat(format, args);
}
}
In order to register it with StructureMap, I used the following code in the registry:
For<ILogger1>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger1).Singleton(); // I want only one logger per type
For<ILogger2>().Use<MyLogger>().Ctor<LoggerType>("loggerName").Is(LoggerType.Logger2).Singleton();
It all works wonderfully. So, thanks to Steven and Rob for their advice. I really learned something. I wish I could upvote an answer and a response more than once.
So, to summarize, I:
Created a separate interface for each kind of logger (even saying it now sounds intuitive).
Created a base interface for the logger interfaces, because for my needs they have the same API (YMMV)
Created one concrete logger adapter that implements both interfaces because that suits my needs (YMMV again)
Share the implementation of the interfaces' API, for the above reasons
Registered each interface to create a concrete logger with a different type passed in the constructor
configured the concrete logger with log4net using a Factory Method to determine which logger to use
As an alterative to the answers above, this can be solved exclusively in StructureMap (and I believe works for the SM version used in the question). You can tell StructureMap exactly how to build MyClass by also including the following in a Registry.
For<MyClass>().Use(x => new MyClass(x.GetInstance<ILog>("Logger1"), x.GetInstance<ILog>("Logger2")));
I think I have stumbled upon a quirk in Simple Injector's RegisterDecorator(). It occurs even in the most recent 2.5.0. I have a situation where I want to decorate a closed generic type, for example ICommandHandler<MessageCommand>, with a decorator that takes (via constructor injection) an inner handler of type ICommandHandler<MessageCommand>, but also another type of handler, say ICommandHandler<LogCommand>. Even though these command handler types are distinct, SimpleInjector seems to get confused and throws an exception when I call RegisterDecorator on such a decorator type:
ArgumentException: For the container to be able to use MessageLogger as a decorator, its constructor must include a single parameter of type ICommandHandler<MessageCommand> (or Func<ICommandHandler<MessageCommand>>) - i.e. the type of the instance that is being decorated. The parameter type ICommandHandler<MessageCommand> is defined multiple times in the constructor of class MessageLogger.
... even though the decorator clearly only has one ICommandHandler<MessageCommand> parameter.
Here is the full working example that throws the exception:
public interface ICommandHandler<T>
{
void Execute(T command);
}
public class LogCommand
{
public string LogMessage { get; set; }
public DateTime Time { get; set; }
}
public class Logger : ICommandHandler<LogCommand>
{
public void Execute(LogCommand command)
{
Debug.WriteLine(string.Format("Message \"{0}\" sent at {1}",
command.LogMessage, command.Time));
}
}
public class MessageCommand
{
public string Message { get; set; }
}
public class MessageSender : ICommandHandler<MessageCommand>
{
public void Execute(MessageCommand command)
{
Debug.WriteLine(command.Message);
}
}
// message command handler decorator that logs about messages being sent
public class MessageLogger : ICommandHandler<MessageCommand>
{
private ICommandHandler<MessageCommand> innerHandler;
private ICommandHandler<LogCommand> logger;
// notice these dependencies are two distinct closed generic types
public MessageLogger(ICommandHandler<MessageCommand> innerHandler,
ICommandHandler<LogCommand> logger)
{
this.innerHandler = innerHandler;
this.logger = logger;
}
public void Execute(MessageCommand command)
{
innerHandler.Execute(command);
var logCommand = new LogCommand
{
LogMessage = command.Message,
Time = DateTime.Now
};
logger.Execute(logCommand);
}
}
// this works as intended, but is tedious in a real-world app
ICommandHandler<MessageCommand> ResolveManually()
{
ICommandHandler<MessageCommand> sender = new MessageSender();
ICommandHandler<LogCommand> logger = new Logger();
ICommandHandler<MessageCommand> loggerSender =
new MessageLogger(sender, logger);
return loggerSender;
}
// this is what I want to work - seems simple?
ICommandHandler<MessageCommand> ResolveWithSimpleInjector()
{
var container = new Container();
container.Register<ICommandHandler<LogCommand>, Logger>();
container.Register<ICommandHandler<MessageCommand>, MessageSender>();
// this next line throws the exception
container.RegisterDecorator(typeof(ICommandHandler<MessageCommand>),
typeof(MessageLogger));
return container.GetInstance<ICommandHandler<MessageCommand>>();
}
void Main()
{
//ICommandHandler<MessageCommand> sender = ResolveManually();
ICommandHandler<MessageCommand> sender = ResolveWithSimpleInjector();
var command = new MessageCommand { Message = "Hello World!" };
sender.Execute(command);
}
I could not find any information about this situation. Is this a bug, or am I missing something?
Edit
I am fishing for feedback from a dev on SimpleInjector to find out if there is a technical reason for this limitation, or it is something that was overlooked... Unless someone can convince me there is a logical flaw in this design and there is a good reason I shouldn't do things this way, which none of the answers thus far have been able to do. I do appreciate the feedback.
It seems to me that the core issue is that RegisterDecorator() is treating two different closed generic types as the same type. There may be a technical reason for this based on its inner workings, but maybe not?
I had to do some investigation in the code base to see what was going one. You might call this a glitch in Simple Injector's implementation, but it's IMO a fair trade off. Simple Injector's decorator sub system is based around the idea of working with open generic types and open generic decorators. The check it does upon decorator registration is to see if a decorator's constructor has only one decoratee. This check is done using the open generic abstraction to which the decorator must be applied; in your case ICommandHandler<T>. Since at that point only the generic ICommandHandler<T> is available, two constructor parameters match this type.
It is possible to improve these pre-condition checks, but this is actually quite nasty, while the usefulness of this feature is very limited. It's limited because it's only useful for non-generic decorators. Take a look at the following decorator for instance:
public class GenericDecorator<TCommand> : ICommandHandler<TCommand> {
public GenericDecorator(
ICommandHandler<TCommand> decoratee,
ICommandHandler<LoggingCommand> dependency)
{
}
}
This decorator is generic and allows you to apply it to any decorator, which is much more useful. But what happens when you resolve an ICommandHandler<LoggingCommand>? That would cause a cyclic dependency graph and Simple Injector will (obviously) not be able to create that graph and will throw an exception. It must throw, since the decorator will in that case have two ICommandHandler<LoggingCommand> arguments. The first will be the decoratee and will be injected with your Logger, and the second will be a normal dependency and will be injected with a GenericDecorator<LoggingCommand>, which is recursive of course.
So I would argue that the problem is in your design. In general I advice against composing command handlers out of other command handlers. The ICommandHandler<T> should be the abstraction that lies on top of your business layer that defines how the presentation layer communicates with the business layer. It's not a mechanism for the business layer to use internally. If you start doing this, your dependency configuration becomes very complicated. Here's an example of a graph that uses DeadlockRetryCommandHandlerDecorator<T> and a TransactionCommandHandlerDecorator<T>:
new DeadlockRetryCommandHandlerDecorator<MessageCommand>(
new TransactionCommandHandlerDecorator<MessageCommand>(
new MessageSender()))
In this case the DeadlockRetryCommandHandlerDecorator<T> and a TransactionCommandHandlerDecorator<T> are applied to the MessageSender command handler. But look what happens we apply your MessageLogger decorator as well:
new DeadlockRetryCommandHandlerDecorator<MessageCommand>(
new TransactionCommandHandlerDecorator<MessageCommand>(
new MessageLogger(
new MessageSender(),
new DeadlockRetryCommandHandlerDecorator<MessageLogger>(
new TransactionCommandHandlerDecorator<MessageLogger>(
new Logger())))))
Notice how there's a second DeadlockRetryCommandHandlerDecorator<T> and a second TransactionCommandHandlerDecorator<T> in the object graph. What does it mean to have a transaction in a transaction and have a nested deadlock retry (within a transaction). This can cause serious reliability problems in your application (since a database deadlock will cause your operation to continue in a transaction-less connection).
Although it is possible to create your decorators in such way that they are able to detect that they are nested to make them work correctly in case they're nested, this makes implementing them much harder and much more fragile. IMO that's a waste of your time.
So instead of allowing command handlers to be nested, let command handlers and command handler decorators depend upon other abstractions. In your case, the problem can be easily fixed by changing your decorator by letting it use an ILogger interface of some sort:
public class MessageLogger : ICommandHandler<MessageCommand> {
private ICommandHandler<MessageCommand> innerHandler;
private ILogger logger;
public MessageLogger(
ICommandHandler<MessageCommand> innerHandler, ILogger logger) {
this.innerHandler = innerHandler;
this.logger = logger;
}
public void Execute(MessageCommand command) {
innerHandler.Execute(command);
logger.Log(command.Message);
}
}
You can still have an ICommandHandler<LogCommand> implementation in case the presentation layer needs to log directly, but in that case that implementation can simply depend on that ILogger as well:
public class LogCommandHandler : ICommandHandler<LogCommand> {
private ILogger logger;
public LogCommandHandler(ILogger logger) {
this.logger = logger;
}
public void Execute(LogCommand command) {
logger(string.Format("Message \"{0}\" sent at {1}",
command.LogMessage, DateTime.Now));
}
}
This is an edge case that you could possibly argue either way but the fact is that Simple Injector explicitly does not support what you are trying to do.
A decorator would normally be required to apply common logic across all (or some) of a particular abstraction, which in your example is ICommandHandler. In other words MessageLogger is designed to decorate ICommandHandler's and as it is a decorator of ICommandHandler's it can only take one ICommandHandler in it's constructor. In addition, allowing something like this would require reams of horrible circular checks that are best avoided with a cleaner design!
As such you would normally define a decorator with the same interface (and generic parameters) as the type it is decorating
public class MessageLogger<TCommand> : ICommandHandler<TCommand>
where TCommand : <some criteria e.g. MessageCommand>
{
//....
}
The first solution I can think of to mitigate your problem is create a mediator to remove the direct dependency:
public class LoggerMediator
{
private readonly ICommandHandler<LogCommand> logger;
public LoggerMediator(ICommandHandler<LogCommand> logger)
{
this.logger = logger;
}
public void Execute(LogCommand command)
{
this.logger.Execute(command);
}
}
And change your MessageLogger to use the mediator.
public class MessageLogger<TCommand> : ICommandHandler<TCommand>
where TCommand : MessageCommand
{
private ICommandHandler<TCommand> innerHandler;
private LoggerMediator logger;
public MessageLogger(
ICommandHandler<TCommand> innerHandler,
LoggerMediator logger)
{
this.innerHandler = innerHandler;
this.logger = logger;
}
public void Execute(TCommand command)
{
innerHandler.Execute(command);
var logCommand = new LogCommand
{
LogMessage = command.Message,
Time = DateTime.Now
};
logger.Execute(logCommand);
}
}
BTW you can simplify your registrations like this
var container = new Container();
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
container.Register<LoggerMediator>();
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(MessageLogger<>));
container.Verify();
UPDATE
Looking through my code base here I have found that I have had a similar requirement and I resolved it with one extra class - a generic command mediator:
public class CommandHandlerMediator<TCommand>
{
private readonly ICommandHandler<TCommand> handler;
public CommandHandlerMediator(ICommandHandler<TCommand> handler)
{
this.handler = handler;
}
public void Execute(TCommand command)
{
this.handler.Execute(command);
}
}
registered like this:
container.RegisterOpenGeneric(
typeof(CommandHandlerMediator<>),
typeof(CommandHandlerMediator<>));
and referenced like this:
public class MessageLogger<TCommand> : ICommandHandler<TCommand>
where TCommand : <some criteria e.g. MessageCommand>
{
private ICommandHandler<TCommand> decorated;
private CommandHandlerMediator<LogCommand> logger;
public MessageLogger(
ICommandHandler<TCommand> decorated,
CommandHandlerMediator<LogCommand> logger)
{
this.innerHandler = innerHandler;
this.logger = logger;
}
//....
}
One new class and you're sorted for all of your handlers.
You can change your Decorator ctor as
public MessageLogger(ICommandHandler<MessageCommand> innerHandler)
{
this.innerHandler = innerHandler;
}
to match the neccessary ctor signature with "a single parameter of type ICommandHandler (or Func>)". And inject logger as a property and not the ctor argument. I didn't work with simple-injector but looking at your exception message it's the most obvious solution, because of decorator constructor signature limitations.
Your solution seems a bit awkward as it is a combination of a decorator and constructor injection/composition (something). While it's not exactly an asnwer to your question, it'll probably solve your problem (in a nicer way I'd say):
public class LoggingHandler : ICommandHandler<MessageCommand>
{
private ICommandHandler<MessageCommand> innerHandler;
public LoggingHandler(ICommandHandler<MessageCommand> innerHandler)
{
this.innerHandler = innerHandler;
}
public void Execute(MessageCommand command)
{
innerHandler.Execute(command);
Debug.WriteLine(string.Format("Message \"{0}\" sent at {1}",
command.Message, DateTime.Now));
}
}
I don't see the need for a separate CommandHandler for a LogMessage. You could just log inside the object that decorates your actual commandhandler. What is its purpose otherwise?
With this approach you have a pure decorator, which is a better solution IMO as it saves you two extra classes.
I have integrated log4net in my app. I have a few helper methods to assist in logging which call log4net. When refactoring, I plan to move these methods to base class so that the code is not repeated in other derived classes.
Without the inheritance model, following worked correctly in each class
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
Placing the above in the base class will return the declaring type as base class and not derived class.
What is an optimal way to move this declaration to the base class?
At present, I can think of a few ways to achieve this but don't find them optimal.
I think I would do this:
LogManager.GetLogger(this.GetType());
Based on Sefan's answer here's how I declared it in the base class
/// <summary>
/// This is delay loaded to allow us to capture the class type of the inherited class on request
/// </summary>
private ILog log = null;
protected ILog Log
{
get
{
if (log == null)
{
log = LogManager.GetLogger(this.GetType());
}
return log;
}
}
We just redeclare it in each class that needs a logger (the point of it being a private static) and use a code snippet to make that as simple as typing log<tab><tab> if you wanted to get extra fancy though you could do something like:
public class Loggable<T> where T : Loggable<T>
{
private static readonly ILog log = LogManager.GetLogger(typeof(T));
protected static ILog Log
{
get
{
return log;
}
}
}
And punch T through your inheritance hierarchy so that it is the most derived class.
The problem with all of the answers here is that you lose information about where log messages are coming from, so I would personally stick to your original code despite the added boilerplate.