Reputation: 191
Can anyone give me some advice. I am using
Microsoft.Extensions.DependencyInjection version 5.0.1 nuget package
and I would like to get a reference to a ViewModel class that needs a service inject to it, and at the same time pass a parameter to the ViewModel. Here I have an example where the
My class calling a ViewModel that needs to pass a parameter to it also. Can someone tell me how I can do this?
public class ThemeManagementPage : HeadingView
{
private readonly ThemeManagementViewModel _vm;
public ThemeManagementPage(int param1)
{
// This page is called with a parameter and then
// whhat I need to do is to pass the parameter `param1`
// to the ViewModel which I have identified
// as a Transient (see bottom of post)
BindingContext = _vm =
Startup.ServiceProvider.GetRequiredService<ThemeManagementViewModel>();
}
}
public partial class ThemeManagementViewModel : BaseViewModel
{
private readonly IResourceService _resourceService;
public ThemeManagementViewModel(IResourceService resourceService, int param1)
{
_resourceService = resourceService;
var x = param1
}
}
For reference here is my DI setup:
public partial class ResourceService : IResourceService
{
private IDatabaseService _databaseService;
public ResourceService(IDatabaseService databaseService)
{
_databaseService = databaseService;
}
}
public interface IResourceService
{
void SetResourceColors();
}
public static class Startup
{
public static IServiceProvider ServiceProvider { get; set; }
public static IServiceProvider Init()
{
var serviceProvider = new ServiceCollection().ConfigureServices()
.BuildServiceProvider();
ServiceProvider = serviceProvider;
return serviceProvider;
}
}
public static class DependencyInjectionContainer
{
public static IServiceCollection ConfigureServices(this IServiceCollection services)
{
services.AddSingleton<IDatabaseService, DatabaseService>();
services.AddSingleton<IResourceService, ResourceService>();
services.AddTransient<ThemeManagementViewModel>();
return services;
}
}
Upvotes: 1
Views: 1414
Reputation: 863
I think you wanted to pass some parameter to viewmodel from view. Below code will do that job.
Create a public property or variable for the parameter and assign.
public partial class ThemeManagementViewModel : BaseViewModel
{
public string Param1 {get; set;}
private readonly IResourceService _resourceService;
public ThemeManagementViewModel(IResourceService resourceService, int param1)
{
_resourceService = resourceService;
this.Param1 = param1
}
}
public class ThemeManagementPage : HeadingView
{
private readonly ThemeManagementViewModel _vm;
public ThemeManagementPage()
{
// What I need to do is to pass a parameter
// to the ViewModel which I have identified
// as a Transient (see bottom of post)
BindingContext = _vm =
Startup.ServiceProvider.GetRequiredService<ThemeManagementViewModel>();
_vm.Param1 = 10; //parameter which you want to pass
}
}
I was not able to comment to your question due to less reputation. Let me know this answers your question.
Upvotes: 1
Reputation: 247641
Since Microsoft.Extensions.DependencyInjection nuget package is being used then consider using
ActivatorUtilities.CreateInstance
Method from the included Microsoft.Extensions.DependencyInjection.Abstractions.dll
Instantiate a type with constructor arguments provided directly and/or from an
IServiceProvider
.
public class ThemeManagementPage : HeadingView {
private readonly ThemeManagementViewModel _vm;
public ThemeManagementPage(int param1) {
_vm = ActivatorUtilities.CreateInstance<ThemeManagementViewModel>(Startup.ServiceProvider, param1);
BindingContext = _vm;
}
//...
}
The ActivatorUtilities.CreateInstance
method will use the service provider to resolve the abstraction and use that along with the other parameter provided to inject into the target type when initializing it.
Design-wise, I am not a particular fan of such Service Locator approaches, but this should provide the desired behavior.
This should be redesigned to allow all the necessary dependencies to be explicitly injected into the view model and not passed through the view constructor but that would depend on the nature of supposed run-time parameter(s) to be injected. Which is currently not clear based on the post as currently written.
Some interesting reading Dependency Injection Code Smell: Injecting runtime data into components
Upvotes: 1