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

.NET 6 WPF单文件发布应用如何正确注册服务?

.NET 6 WPF单文件发布服务注册问题解决

问题根源

单文件发布默认启用**剪裁(Trim)**机制,会自动移除未被直接静态引用的类型。你的代码中DrugVerificationApi和TestDrugVerificationApi是通过工厂方法动态获取的,剪裁工具无法识别这种动态依赖,导致这两个类型被移除,运行时无法解析。

解决方案

方案1:禁用剪裁(简单直接)

如果不需要减小单文件体积,可以在项目文件(.csproj)中关闭剪裁:

<PropertyGroup>
  <PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>

方案2:保留动态依赖类型(推荐,兼顾体积)

通过特性标记需要保留的类型,告诉剪裁工具不要移除这些动态引用的类:
在你的服务扩展方法所在的类上添加[DynamicDependency]特性:

using System.Diagnostics.CodeAnalysis;

[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(DrugVerificationApi))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(TestDrugVerificationApi))]
public static class DrugVerificationServiceExtensions
{
    public static IServiceCollection AddDrugVerificationModule(this IServiceCollection services)
    {
        services.AddTransient<DrugVerificationApi>();
        services.AddTransient<TestDrugVerificationApi>();
        services.AddTransient<IDrugVerificationService, DrugVerificationService>();

        services.AddTransient<IDrugVerificationApi>(provider =>
            provider.GetRequiredService<IOptions<VerificationOptions>>().Value.UseTestVerification
                ? provider.GetRequiredService<TestDrugVerificationApi>()
                : provider.GetRequiredService<DrugVerificationApi>());

        return services;
    }
}

方案3:重构为条件注册(避免动态解析)

提前根据配置决定注册哪个实现类,让剪裁工具能识别静态依赖:

public static IServiceCollection AddDrugVerificationModule(this IServiceCollection services)
{
    services.AddTransient<IDrugVerificationService, DrugVerificationService>();

    // 先注册配置(确保已提前配置VerificationOptions)
    services.AddOptions<VerificationOptions>().BindConfiguration("Verification");

    // 使用服务提供者工厂获取配置,避免提前BuildServiceProvider
    services.AddTransient<IDrugVerificationApi>(sp =>
    {
        var options = sp.GetRequiredService<IOptions<VerificationOptions>>().Value;
        return options.UseTestVerification 
            ? ActivatorUtilities.CreateInstance<TestDrugVerificationApi>(sp) 
            : ActivatorUtilities.CreateInstance<DrugVerificationApi>(sp);
    });

    // 确保两个实现类被注册(供ActivatorUtilities使用)
    services.AddTransient<DrugVerificationApi>();
    services.AddTransient<TestDrugVerificationApi>();

    return services;
}

这种方式通过ActivatorUtilities显式创建实例,同时保留了动态切换的能力,也能让剪裁工具识别到依赖。

额外注意事项

  • 如果你的实现类依赖了原生DLL,需要在项目文件中显式包含这些文件:
<ItemGroup>
  <NativeFileReference Include="path/to/your/native.dll" />
</ItemGroup>
  • 发布单文件时,建议测试SelfContained模式(<SelfContained>true</SelfContained>),确保所有依赖都被正确打包。

内容的提问来源于stack exchange,提问作者daily_driver

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 13:32:31