How to Use in a ContentView
Closed this issue · 1 comments
How would I use/provide this ILocalizationResourceManager instance to a Code-Behind of a ContentView?
I registered the Code-Behind in MauiProgram.cs via builder.Services.AddTransient<MyContentView>();
, but when I try to use it as follows, it just says that it can't be used like this and needs a default constructor. So, how would I use this in a ContentView?
public partial class MyContentView : ContentView
{
private readonly ILocalizationResourceManager resourceManager;
public MyContentView(ILocalizationResourceManager resourceManager)
{
}
}
@DeveloperOnGitHub, unfortunately a ContentView
will not be automatically resolved from the DI container. So that means you have to resolve the ContentView
or ILocalizationResourceManager
by yourself. To accomplish this, you need a reference to the DI ServiceProvider
.
This could be solved in many ways, but I am fond of using a static class to store and access the ServiceProvider
:
/// <summary>
/// Store and access a service provider to resolve specific types.
/// </summary>
internal static class ServiceResolver
{
private static IServiceProvider? _serviceProvider;
public static IServiceProvider ServiceProvider => _serviceProvider ?? throw new Exception("Service provider has not been initialized");
/// <summary>
/// Register the service provider
/// </summary>
public static void RegisterServiceProvider(IServiceProvider sp)
{
_serviceProvider = sp;
}
/// <summary>
/// Get service of type <typeparamref name="T"/> from the service provider.
/// </summary>
public static T Resolve<T>() where T : class
=> ServiceProvider.GetRequiredService<T>();
public static void UseResolver(this IServiceProvider sp)
{
RegisterServiceProvider(sp);
}
}
Register the ServiceProvider
with the UseResolver
extension method or the RegisterServiceProvider
method. Get the ServiceProvider
reference in the CreateMauiApp
method in MauiProgram.cs
or my prefered way, inject the IServiceProvider
interface in a custom Application
class:
/// <summary>
/// Custom Application for Service Provider registering.
/// </summary>
/// <remarks>Use as new App base class for Maui Application!</remarks>
public abstract class ServiceProviderApplication : Application
{
/// <summary>
/// Constructor for injecting current Service Provider.
/// </summary>
/// <param name="serviceProvider">Current Service Provider.</param>
public ServiceProviderApplication(IServiceProvider serviceProvider)
{
//Store Current Service Provider
serviceProvider.UseResolver();
}
}
Update your App.xaml
AND App.xaml.cs
to use the the custom Application
class:
public partial class App : ServiceProviderApplication
{
public App(IServiceProvider serviceProvider) : base(serviceProvider)
{
InitializeComponent();
Now you can access the ServiceProvider
anywhere in your application and resolve anything registered in DI! 😃
In your case, you could resolve the ILocalizationResourceManager
:
public partial class MyContentView : ContentView
{
private readonly ILocalizationResourceManager resourceManager;
public MyContentView()
{
resourceManager = ServiceResolver.Resolve<ILocalizationResourceManager>();
}
}
Come to think of it, I should probably write a blog about this! 😜
Hope this helps!