如何基于参数实现依赖注入?条件注入失效解决方案
你原来的写法行不通,因为@inject是编译阶段的指令,不是运行时的条件逻辑。编译器会处理所有的@inject语句,最后变量vm会被后面的注入语句覆盖,所以不管tranArg是什么值,最终都会用第二个注入的实例。
以下是两种可行的实现方式:
方法一:通过IServiceProvider手动获取实例
直接在组件中注入IServiceProvider,然后在参数更新时根据tranArg获取对应的ViewModel实例:
@inject IServiceProvider ServiceProvider @* 这里可以直接使用vm的属性,比如@vm.Model.SomeProperty *@ @code { [Parameter] public string tranArg { get; set; } private Csla.Blazor.ViewModelBase vm; // 用ViewModel基类统一类型 protected override void OnParametersSet() { base.OnParametersSet(); // 根据参数选择对应的ViewModel vm = tranArg switch { "apin" => ServiceProvider.GetRequiredService<Csla.Blazor.ViewModel<FezWeb.BizObj.AP_APIN>>(), "arin" => ServiceProvider.GetRequiredService<Csla.Blazor.ViewModel<FezWeb.BizObj.AR_ARIN>>(), _ => throw new ArgumentException($"不支持的tranArg值:{tranArg}") }; // 如果需要初始化ViewModel(比如加载数据),可添加异步逻辑 // await vm.LoadAsync(); } }
方法二:封装工厂类(更符合DI设计原则)
创建一个工厂类封装ViewModel的创建逻辑,避免直接在组件中依赖IServiceProvider:
- 定义工厂接口和实现:
public interface IViewModelFactory { Csla.Blazor.ViewModelBase CreateViewModel(string tranArg); } public class ViewModelFactory : IViewModelFactory { private readonly IServiceProvider _serviceProvider; public ViewModelFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public Csla.Blazor.ViewModelBase CreateViewModel(string tranArg) { return tranArg switch { "apin" => _serviceProvider.GetRequiredService<Csla.Blazor.ViewModel<FezWeb.BizObj.AP_APIN>>(), "arin" => _serviceProvider.GetRequiredService<Csla.Blazor.ViewModel<FezWeb.BizObj.AR_ARIN>>(), _ => throw new ArgumentException($"不支持的tranArg值:{tranArg}") }; } }
- 在Program.cs中注册工厂和ViewModel类型:
// 注册ViewModel到DI容器 builder.Services.AddScoped<Csla.Blazor.ViewModel<FezWeb.BizObj.AP_APIN>>(); builder.Services.AddScoped<Csla.Blazor.ViewModel<FezWeb.BizObj.AR_ARIN>>(); // 注册工厂 builder.Services.AddScoped<IViewModelFactory, ViewModelFactory>();
- 在组件中使用工厂:
@inject IViewModelFactory ViewModelFactory @* 使用vm的内容 *@ @code { [Parameter] public string tranArg { get; set; } private Csla.Blazor.ViewModelBase vm; protected override void OnParametersSet() { base.OnParametersSet(); vm = ViewModelFactory.CreateViewModel(tranArg); // 按需执行异步初始化 // await vm.LoadAsync(); } }
注意事项
- 确保所有需要的ViewModel类型都已注册到DI容器中,否则
GetRequiredService会抛出异常。 - 如果
AP_APIN和AR_ARIN有共同的基类或接口,建议将vm的类型声明为该基类/接口,方便后续统一调用方法。 - 若需要异步初始化逻辑,可将
OnParametersSet改为OnParametersSetAsync并使用await执行相关操作。
内容的提问来源于stack exchange,提问作者BlazorWolf
相关产品推荐
相关产品推荐

