I've got a PRISM (8.1.97) WPF application running on .net5.0 with the unity container.
What I would like to do is to assign Serilog as my logging provider, but inject the usual Microsoft.Extensions.Logging
logger through the constructor of my DI registered services (eg, just use ILogger<MyService> logger
in constructors).
After some digging around I found some clues here and here.
Of these, the second one is the most straightforward. Basically you add Prism.Container.Extensions and then in App.xaml.cs, override CreateContainerExtension(). This gives you a way to access a service collection that seems just like what you get with the built-in .net 5 DI.
Below my App class from App.xaml.cs...
public partial class App : PrismApplication
{
private IConfigurationRoot configRoot;
protected override Window CreateShell()
{
// Configures logger using json config file
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configRoot)
.CreateLogger();
return Container.Resolve<MainWindow>();
}
protected override IContainerExtension CreateContainerExtension()
{
configRoot = new ConfigurationBuilder()
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT")}.json", optional: false)
.Build();
IContainerExtension containerExtension = base.CreateContainerExtension();
containerExtension.RegisterServices(
services =>
{
// Makes serilog the logging provider?
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
});
return containerExtension;
}
protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
// just a simple module with Views/viewModels
var moduleAType = typeof(DevTestingModule);
moduleCatalog.AddModule(new ModuleInfo()
{
ModuleName = moduleAType.Name,
ModuleType = moduleAType.AssemblyQualifiedName,
InitializationMode = InitializationMode.WhenAvailable
});
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
// intentionally empty
}
}
The above seems reasonable, but the problem is when I try to inject a logger, for example in MainWindow (the Prism Shell), it gives an exception upon Container.Resolve<MainWindow>();
in CreateShell() in App.xaml.cs.
Here's my MainWindow.xaml.cs class, when I try to inject a logger...
public partial class MainWindow : Window
{
private readonly ILogger<MainWindow> log;
public MainWindow(ILogger<MainWindow> log)
{
InitializeComponent();
this.log = log;
log.LogInformation("hello?");
}
}
The Exception is a Prism.Ioc.ContainerResolutionException
and the most notable inner exception is ...
No public constructor is available for type System.IServiceProvider.
I think I bungled something, but I am not sure if I am even on the right track here. It seems like the intention of the CreateContainerExtension()
override from Prism.Container.Extensions is to give me a IServiceCollection that can be used like in Microsoft's DI from .net 5. Am I misinterpreting it?