.net5.0 PRISM WPF application, how to use Microsoft.Exensions.Logging with Serilog as provider?

1.2k Views Asked by At

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?

0

There are 0 best solutions below