I am using a custom async target that writes logs to Splunk with NLog (5.0.1.) in my .NET 6 application. I want to leverage IHttpClientFactory in ASP.NET Core.
In my startup.cs, under ConfigureServices(), I register my new target and NLog configuration file.
Target.Register<SplunkTarget>("Splunk");
LogManager.LoadConfiguration("NLog.config");
When I try to inject the IHttpClientFactory
into my target class's instructor like this:
private readonly IHttpClientFactory _clientFactory;
public SplunkTarget(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
I'm unable to start the application because I get the error:
Exception thrown: 'System.MissingMethodException' in System.Private.CoreLib.dll: 'Cannot dynamically create an instance of type 'MyNamespace.SplunkTarget'. Reason: No parameterless constructor defined.'
How do I use the built-in .NET Core HttpFactory so that I don't have to manually create a Httpclient
?
With NLog 5.0 then you can resolve dependencies during initialization:
public class MyCustomTarget : AsyncTaskTarget
{
protected override void InitializeTarget()
{
// ResolveService will throw if dependency is not available,
// and target-initialization will retry when dependency is available
var clientFactory = ResolveService<IHttpClientFactory>();
}
}
If the target must work at startup, then you must register the singleton-interface upfront:
NLog.LogManager.Setup().SetupExtensions(ext => ext.RegisterSingletonService<IHttpClientFactory>(clientFactory));
But you are also allowed to post-pone the registration until UseNLog()
or AddNLog()
are called, and the Microsoft ServiceProvider is registered as external dependency-injection-provider (All LogEvents generated until that point will be cached and released on target-initialization success).
See also: https://github.com/NLog/NLog/wiki/Dependency-injection-with-NLog
P.S. Before NLog 5.0 then one could override the factory-method like this, and perform the dependency injection:
var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
ConfigurationItemFactory.Default.CreateInstance.CreateInstance = type =>
{
if (type == typeof(MyCustomTarget))
return new MyCustomTarget(myCustomParameter);
return defaultConstructor(type);
};