【问题标题】:How can I send a parameter to a ViewModel that I get a reference to with this: Startup.ServiceProvider.GetRequiredService?如何将参数发送到我得到引用的 ViewModel:Startup.ServiceProvider.GetRequiredService?
【发布时间】:2021-05-09 10:37:18
【问题描述】:

谁能给我一些建议。我正在使用

Microsoft.Extensions.DependencyInjection 版本 5.0.1 nuget 包

并且我想获得对需要对其进行服务注入的 ViewModel 类的引用,同时将参数传递给 ViewModel。这里我有一个例子,其中

我的班级调用 ViewModel 也需要向其传递参数。谁能告诉我怎么做?

 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
    }
 }

以下是我的 DI 设置供参考:

 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;
    }
 }

【问题讨论】:

  • 当页面被调用时,一个参数被传递给它。因此,例如,可能会将 Id 传递到显示汽车信息的页面。然后我想为该页面创建一个 ViewModel 并需要将 Id 值传递给该视图模型。 Ranjit 提到刚刚做 _vm.Param1 = 10 但我不确定这是否是正确的方法。在我开始使用 DI 之前,我只是在做 _vm = new ThemeManagementViewModel(Id);但现在有了 DI,我不能 100% 确定如何正确地做到这一点。

标签: c# .net xamarin xamarin.forms dependency-injection


【解决方案1】:

我认为您想将一些参数从视图传递给视图模型。下面的代码将完成这项工作。

为参数创建一个公共属性或变量并赋值。

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
  }
}

由于声誉较低,我无法对您的问题发表评论。让我知道这回答了你的问题。

【讨论】:

    【解决方案2】:

    由于正在使用 Microsoft.Extensions.DependencyInjection nuget 包,因此请考虑使用

    ActivatorUtilities.CreateInstance 来自包含的Microsoft.Extensions.DependencyInjection.Abstractions.dll 的方法

    使用直接提供和/或来自IServiceProvider 的构造函数参数来实例化类型。

    public class ThemeManagementPage : HeadingView {
        private readonly ThemeManagementViewModel _vm;
    
        public ThemeManagementPage(int param1) {
            _vm = ActivatorUtilities.CreateInstance<ThemeManagementViewModel>(Startup.ServiceProvider, param1);
            BindingContext  = _vm;
        }
    
        //...
     }
    

    ActivatorUtilities.CreateInstance 方法将使用服务提供者来解析抽象,并在初始化时使用它与提供的其他参数一起注入目标类型。

    在设计方面,我不是这种服务定位器方法的特别粉丝,但这应该提供所需的行为。

    这应该被重新设计,以允许将所有必要的依赖项显式注入到视图模型中,而不是通过视图构造函数传递,但这将取决于要注入的假定运行时参数的性质。根据当前撰写的帖子,目前尚不清楚。

    一些有趣的阅读Dependency Injection Code Smell: Injecting runtime data into components

    【讨论】:

      猜你喜欢
      • 2011-02-19
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-27
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多