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

WPF应用中如何基于用户启动时的选择配置依赖注入?

基于用户选择动态配置WPF依赖注入的方案

针对你遇到的「需用户选择云服务后再配置依赖注入」的场景,提供两种可行实现方式:

方式一:延迟注册具体服务实现

核心思路是先初始化DI宿主但不绑定ICloudService的具体实现,待用户完成选择后再动态注册对应服务,后续整个应用即可统一使用该实例。

1. 调整App.xaml.cs的启动逻辑

修改OnStartup方法,先显示云服务选择窗口,根据用户选择完成服务注册后再启动主窗口:

public partial class App : Application
{
    public static IHost Host { get; private set; }

    protected override void OnStartup(StartupEventArgs e)
    {
        // 初始化宿主,仅注册必要服务(暂不绑定ICloudService的具体实现)
        Host = new HostBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddTransient<MainWindow>();
                // 注册其他业务服务...
            })
            .Build();

        // 显示云服务选择窗口
        var selectionWindow = new CloudServiceSelectionWindow();
        if (selectionWindow.ShowDialog() == true)
        {
            // 根据用户选择动态注册ICloudService实现
            ConfigureCloudService(selectionWindow.SelectedServiceType);
            
            // 启动主窗口
            var mainWindow = Host.Services.GetRequiredService<MainWindow>();
            mainWindow.Show();
        }
        else
        {
            // 用户取消选择,退出应用
            Shutdown();
        }

        base.OnStartup(e);
    }

    private void ConfigureCloudService(Type serviceType)
    {
        // 将选中的云服务实现注册为ICloudService的Scoped实例
        var serviceCollection = Host.Services.GetRequiredService<IServiceCollection>();
        serviceCollection.AddScoped(typeof(ICloudService), serviceType);
    }
}

2. 实现云服务选择窗口

创建选择窗口,让用户通过下拉框选定云服务,并返回选中的服务类型:

XAML代码(CloudServiceSelectionWindow.xaml)

<Window x:Class="YourAppNamespace.CloudServiceSelectionWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:YourAppNamespace"
        Title="选择云服务" Height="160" Width="320">
    <StackPanel Margin="20">
        <Label Content="请选择要使用的云服务:"/>
        <ComboBox x:Name="ServiceComboBox" Margin="0,10,0,0" SelectedIndex="0">
            <ComboBoxItem Tag="{x:Type local:CloudOneService}">云服务1</ComboBoxItem>
            <ComboBoxItem Tag="{x:Type local:CloudTwoService}">云服务2</ComboBoxItem>
        </ComboBox>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,20,0,0">
            <Button Content="确定" Width="80" Margin="0,0,10,0" Click="Ok_Click"/>
            <Button Content="取消" Width="80" Click="Cancel_Click"/>
        </StackPanel>
    </StackPanel>
</Window>

后台代码(CloudServiceSelectionWindow.xaml.cs)

public partial class CloudServiceSelectionWindow : Window
{
    public Type SelectedServiceType { get; private set; }

    public CloudServiceSelectionWindow()
    {
        InitializeComponent();
    }

    private void Ok_Click(object sender, RoutedEventArgs e)
    {
        if (ServiceComboBox.SelectedItem is ComboBoxItem selectedItem)
        {
            SelectedServiceType = selectedItem.Tag as Type;
            DialogResult = true;
            Close();
        }
    }

    private void Cancel_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = false;
        Close();
    }
}

3. 在业务代码中使用

后续在需要ICloudService的类中,直接通过构造函数注入即可:

public class FileOperationViewModel
{
    private readonly ICloudService _cloudService;

    public FileOperationViewModel(ICloudService cloudService)
    {
        _cloudService = cloudService;
    }

    public void UploadFile(string filePath)
    {
        _cloudService.UploadFile(filePath);
    }
}

方式二:使用工厂模式创建服务

如果需要更灵活的服务创建逻辑(比如后续支持切换场景),可以通过工厂模式延迟实例化ICloudService。

1. 定义服务工厂

public interface ICloudServiceFactory
{
    ICloudService CreateCloudService(Type serviceType);
}

public class CloudServiceFactory : ICloudServiceFactory
{
    private readonly IServiceProvider _serviceProvider;

    public CloudServiceFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ICloudService CreateCloudService(Type serviceType)
    {
        return (ICloudService)_serviceProvider.GetRequiredService(serviceType);
    }
}

2. 调整App.xaml.cs的服务注册

提前注册所有云服务实现和工厂,再根据用户选择创建对应实例:

protected override void OnStartup(StartupEventArgs e)
{
    Host = new HostBuilder()
        .ConfigureServices((context, services) =>
        {
            // 注册所有云服务实现
            services.AddTransient<CloudOneService>();
            services.AddTransient<CloudTwoService>();
            // 注册工厂
            services.AddSingleton<ICloudServiceFactory, CloudServiceFactory>();
            services.AddTransient<MainWindow>();
        })
        .Build();

    var selectionWindow = new CloudServiceSelectionWindow();
    if (selectionWindow.ShowDialog() == true)
    {
        // 获取工厂并创建选中的云服务实例,传递给主窗口
        var factory = Host.Services.GetRequiredService<ICloudServiceFactory>();
        var cloudService = factory.CreateCloudService(selectionWindow.SelectedServiceType);
        var mainWindow = new MainWindow(cloudService);
        mainWindow.Show();
    }
    else
    {
        Shutdown();
    }

    base.OnStartup(e);
}

3. 在主窗口中使用

public partial class MainWindow : Window
{
    private readonly ICloudService _cloudService;

    public MainWindow(ICloudService cloudService)
    {
        InitializeComponent();
        _cloudService = cloudService;
    }

    // 业务逻辑中直接使用_cloudService
}

方案对比

  • 延迟注册方式:适合全局统一使用同一云服务实例的场景,所有依赖ICloudService的类都会自动获取用户选择的实现,无需额外处理。
  • 工厂模式:更灵活,支持动态创建不同实例,若后续需要扩展多服务切换逻辑(即使当前场景要求重启),改造成本更低。

内容的提问来源于stack exchange,提问作者Álvaro García

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:31:58