You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于参数实现依赖注入?条件注入失效解决方案

你原来的写法行不通,因为@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:

  1. 定义工厂接口和实现:
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}")
        };
    }
}
  1. 在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>();
  1. 在组件中使用工厂:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:22:43