maui
maui copied to clipboard
Enable Scope Validation for dependency injection in .NET MAUI during development
One source of common user errors is misconfiguring services in DI. For example, setting up a singleton service that depends on a scoped service 😱. The DI system has a feature, scope validation, for detecting these issues, but we don't turn it on for .NET MAUI apps. We do enable scope validation in ASP.NET Core apps during development, but it doesn't look like we do that for .NET MAUI apps. It seems like we should.
@davidfowl
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
It seems .NET MAUI might have some issues when I turn on scope validation! We might have to fix a few service scoping issues before we could consider enabling this. A good idea, nevertheless!
To anyone watching:
To turn on scope validation in .NET MAUI change MauiAppBuilder's call to BuildServiceProvider() to pass in validateScopes: true on this line:
https://github.com/dotnet/maui/blob/main/src/Core/src/Hosting/MauiAppBuilder.cs#L151
Like this:
IServiceProvider serviceProvider = _createServiceProvider != null
? _createServiceProvider()
: _services.BuildServiceProvider(validateScopes: true); // <--- this line
And sadly, when I run the Maui.Controls.Sample app I immediately get this exception on startup:
System.InvalidOperationException
HResult=0x80131509
Message=Cannot resolve scoped service 'Microsoft.Maui.Dispatching.IDispatcher' from root provider.
Source=Microsoft.Extensions.DependencyInjection
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
Microsoft.Extensions.DependencyInjection.dll!Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(System.Type serviceType = {Name = "IDispatcher" FullName = "Microsoft.Maui.Dispatching.IDispatcher"}, Microsoft.Extensions.DependencyInjection.IServiceScope scope = {Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope}, Microsoft.Extensions.DependencyInjection.IServiceScope rootScope = {Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope}) Unknown
Microsoft.Extensions.DependencyInjection.dll!Microsoft.Extensions.DependencyInjection.ServiceProvider.OnResolve(System.Type serviceType = {Name = "IDispatcher" FullName = "Microsoft.Maui.Dispatching.IDispatcher"}, Microsoft.Extensions.DependencyInjection.IServiceScope scope = {Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope}) Unknown
Microsoft.Extensions.DependencyInjection.dll!Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(System.Type serviceType = {Name = "IDispatcher" FullName = "Microsoft.Maui.Dispatching.IDispatcher"}, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope serviceProviderEngineScope = {Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope}) Unknown
Microsoft.Extensions.DependencyInjection.dll!Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(System.Type serviceType = {Name = "IDispatcher" FullName = "Microsoft.Maui.Dispatching.IDispatcher"}) Unknown
Microsoft.Extensions.DependencyInjection.Abstractions.dll!Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(System.IServiceProvider provider = {Microsoft.Extensions.DependencyInjection.ServiceProvider}, System.Type serviceType = {Name = "IDispatcher" FullName = "Microsoft.Maui.Dispatching.IDispatcher"}) Unknown
Microsoft.Extensions.DependencyInjection.Abstractions.dll!Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<Microsoft.Maui.Dispatching.IDispatcher>(System.IServiceProvider provider = {Microsoft.Extensions.DependencyInjection.ServiceProvider}) Unknown
> Microsoft.Maui.dll!Microsoft.Maui.Hosting.MauiAppBuilder.MauiCoreInitializer.Initialize(System.IServiceProvider services = {Microsoft.Extensions.DependencyInjection.ServiceProvider}) Line 58 C#
Microsoft.Maui.dll!Microsoft.Maui.Hosting.MauiAppBuilder.Build() Line 163 C#
Maui.Controls.Sample.dll!Maui.Controls.Sample.MauiProgram.CreateMauiApp() Line 274 C#
Maui.Controls.Sample.dll!Maui.Controls.Sample.Platform.App.CreateMauiApp() Line 13 C#
Microsoft.Maui.dll!Microsoft.Maui.MauiWinUIApplication.OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args = {Microsoft.UI.Xaml.LaunchActivatedEventArgs}) Line 23 C#
> Microsoft.Maui.dll!Microsoft.Maui.Hosting.MauiAppBuilder.MauiCoreInitializer.Initialize(System.IServiceProvider services = {Microsoft.Extensions.DependencyInjection.ServiceProvider}) Line 58 C#`
Does this mean that MauiCoreInitializer ought to be an IMauiInitializeScopedService?