-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Dependency injection with NLog
NLog 5.0 makes it possible to resolve interfaces using dependency injection during initialization. This allows you to load targets using NLog config file, before dependency injection provider is available.
The custom NLog target can then override InitializeTarget
to resolve the necessary dependencies:
protected override void InitializeTarget()
{
var wantedDependency = base.ResolveService<IWantedDependency>();
base.InitializeTarget();
}
If the custom NLog target requests a dependency, that is unavailable, then NLog will perform re-initialization of the NLog when the dependency becomes available. Service interfaces can registered like this:
NLog.LogManager.Setup().SetupExtensions(ext => RegisterSingletonService<IWantedDependency>(wantedInstance));
It is also possible to connect with an external IServiceProvider
for resolving dependencies:
NLog.LogManager.Setup().SetupExtensions(ext => RegisterServiceProvider(serviceProvider));
It is recommended to setup dependency-injection early before loading the NLog LoggingConfiguration, or else they might not take effect.
NLog v5.2 introduces the ability to register extensions together with custom factory-method:
NLog.LogManager.Setup().SetupExtensions(ext => RegisterTarget<MyTarget>(() => new MyTarget(wantedDependency));
⚠️ NLog v5.2 has markedConfigurationItemFactory.CreateInstance
as obsolete, as it doesn't work well with Ahead-of-Time (AOT) application trimming in .NET
NLog will by default use the default constructor for creating new objects. It is possible to override the creation by using ConfigurationItemFactory.CreateInstance
. Example:
using NLog.Config;
var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
ConfigurationItemFactory.Default.CreateInstance.CreateInstance = type =>
{
if (type == typeof(MyCustomTarget))
return new MyCustomTarget(myCustomParameter);
return defaultConstructor(type);
};
NLog will only be able to create objects of known types. To support custom objects one must also register the config-item-type before it will be recognized. See also Register your custom component
The combination of dynamic logging configuration and dependency injection can give a catch22. You want to have logging up and running early, but this will fail if dependent on custom objects that requires a dependency injection provider is fully loaded.
The "ugly" work-around to this catch22 is to have two constructors for your custom-objects:
- Default Constructor that initializes an object in disabled state (Ignored by dependency injection provider).
- Specialized Constructor that initializes an object in working state.
Alternative override the CreateInstance
-method as first thing (Before creating first Logger-object or loading NLog config). Where it calls the specialized constructor with parameters that signals that it should be in disabled state.
Then one can "just" perform a reload of the NLog config, after the dependency injection provider has been fully loaded and performed final override of CreateInstance
. This will make NLog recreate all configuration items once again, and now with a working dependency injection provider that calls the specialized constructor with correct parameters.
using NLog;
LogManager.Configuration = LogManager.Configuration.Reload();
See also Reinitialize NLog configuration
- Troubleshooting Guide - See available NLog Targets and Layouts: https://nlog-project.org/config
- Getting started
- How to use structured logging
- Troubleshooting
- FAQ
- Articles about NLog
-
All targets, layouts and layout renderers
Popular: - Using NLog with NLog.config
- Using NLog with appsettings.json