Reputation: 311
I have a custom NLog log target class that looks like this:
public class MyTarget : AsyncTaskTarget
{
public MyTarget() {}
public MyTarget(INeedThisThingToFunction thing)
{
Thing = thing;
}
public INeedThisThingToFunction Thing { get; set; }
public override Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
{
Thing.Use();
return null;
}
}
I cannot figure out how to ensure that the second constructor gets called. I've done this in Program.cs:
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
ConfigureLogging(host.Services.GetAutofacRoot());
LogManager.GetCurrentClassLogger().Info("Hi mom");
host.Run();
}
private static void ConfigureLogging(IComponentContext container) {
ConfigurationItemFactory.Default.CreateInstance = type =>
{
if (type != typeof(MyTarget) return Activator.CreateInstance(type);
var thing = new ThingTheTargetNeedsToFunction();
return new MyTarget(thing);
}
LogManager.Configuration.Reload();
}
I've tried a number of other things, too, but that comes the closest to doing something. When LogManager.Configuration.Reload()
is called, the CreateInstance
code fires; but when the Info
method fires, the Thing
property on the target is null.
Is there a better way to do this? Like, a way that works?
Using .NET Core 3, NLog, Autofac.
Upvotes: 0
Views: 1940
Reputation: 19867
If the Thing
is only available after having built the host
, then you can do it like this:
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).UseNLog().Build();
ConfigureLogging(host.Services.GetAutofacRoot());
LogManager.GetCurrentClassLogger().Info("Hi mom");
host.Run();
}
private static void ConfigureLogging(IComponentContext container)
{
var defaultConstructor = ConfigurationItemFactory.Default.CreateInstance;
ConfigurationItemFactory.Default.CreateInstance.CreateInstance = type =>
{
if (type == typeof(MyTarget))
{
var thing = new ThingTheTargetNeedsToFunction();
return new MyTarget(thing);
}
return defaultConstructor(type);
};
// Reload config and assign the newly reloaded config
LogManager.Configuration = LogManager.Configuration?.Reload();
}
Then make sure that your custom MyTarget
can handle that it is running in "disabled mode" where Thing
is unassigned:
[Target("MyTarget")]
public class MyTarget : AsyncTaskTarget
{
public MyTarget() {}
public MyTarget(INeedThisThingToFunction thing)
{
Thing = thing;
}
public INeedThisThingToFunction Thing { get; set; }
public override await Task WriteAsyncTask(LogEventInfo logEvent, CancellationToken cancellationToken)
{
if (Thing == null)
return null; // Handle that `Thing` is unassigned by default-constructor
await Thing.UseAsync().ConfigureAwait(false);
}
}
Upvotes: 1