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

.NET 8 Minimal API+MediatR 12.2.0 Docker部署IoC构造异常

问题:.NET 8 Minimal API部署Docker后MediatR构造函数解析失败

问题背景

我有一个使用MediatR v12.2.0的.NET 8 Minimal API项目,在Visual Studio 2022中调试运行正常,但部署到Docker后启动时抛出未处理的AggregateException。项目在.NET 6版本时可正常运行,仅升级到.NET 8并更新引用库后出现此问题。

错误日志

2024-01-31 17:56:50 Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IMediator Lifetime: Transient ImplementationType: MediatR.Mediator': A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.)
2024-01-31 17:56:50 ---> System.InvalidOperationException: Error while validating the service descriptor 'ServiceType: MediatR.IMediator Lifetime: Transient ImplementationType: MediatR.Mediator': A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
2024-01-31 17:56:50 ---> System.InvalidOperationException: A suitable constructor for type 'MediatR.Mediator' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache, ServiceIdentifier, Type , CallSiteChain)
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor, ServiceIdentifier, CallSiteChain, Int32)
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(ServiceDescriptor, CallSiteChain)
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor)
2024-01-31 17:56:50 --- End of inner exception stack trace ---
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(ServiceDescriptor)
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1, ServiceProviderOptions) 2024-01-31 17:56:50 --- End of inner exception stack trace --- 2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection1, ServiceProviderOptions)
2024-01-31 17:56:50 at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection, ServiceProviderOptions)
2024-01-31 17:56:50 at Microsoft.Extensions.Hosting.HostApplicationBuilder.<>c__DisplayClass12_0.<.ctor>b__0()
2024-01-31 17:56:50 at Microsoft.Extensions.Hosting.HostApplicationBuilder.Build()
2024-01-31 17:56:50 at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
2024-01-31 17:56:50 at Program.<Main>$(String[]) in /app/apis/services/Pique.Services/Program.cs:line 119
2024-01-31 17:56:50 at Program.<Main>(String[])

已尝试的MediatR注册方式

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
builder.Services.AddMediatR(config => { config.RegisterServicesFromAssemblyContaining<Program>(); });

相关代码文件

Program.cs

using Dapper.FluentMap;
using Microsoft.OpenApi.Models;
using Pique.Common.Exceptions;
using Pique.Services.Endpoints;
using Pique.Services.Handlers.DoloDocs;
using Pique.Services.Middleware;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// Register MediatR
//builder.Services.AddMediatR(config => {
//    config.RegisterServicesFromAssembly(typeof(Pique.Services.AutoMapperProfile).Assembly);
//});
//builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly()));
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(Program).GetTypeInfo().Assembly));

// Register Automapper
builder.Services.AddAutoMapper(config =>
{
    config.AddProfile<Pique.Services.AutoMapperProfile>();
});


var app = builder.Build();

app.UseCors();

// Add global exception handler
app.UseMiddleware<ExceptionMiddleware>();

// Add claims middleware - Used for Authentication & Authorization
app.UseMiddleware<ClaimsMiddleware>();

// Add request logging middleware
app.UseMiddleware<Pique.Common.RequestLoggerMiddleware>();

// Use Swagger UI to display the documentation
app.UseSwagger();
app.UseSwaggerUI(o =>
{
    o.DefaultModelsExpandDepth(-1);
});


await app.RunAsync();

Dockerfile

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env

EXPOSE 8080

# copy api project
COPY /apis/services/Services/ ./apis/services/Services/

# build out the solution
WORKDIR /app/apis/services/Services
RUN dotnet restore
RUN dotnet publish -c Release --self-contained true /p:PublishTrimmed=true -o /out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
COPY --from=build-env /out .

ENTRYPOINT ["dotnet", "Services.dll"]

问题分析与解决方案

错误核心是Docker构建时启用的PublishTrimmed=true裁剪功能,移除了MediatR构造函数依赖的必要类型。本地调试未启用裁剪,因此运行正常;.NET 8的裁剪规则比.NET 6更严格,导致该问题暴露。

解决方法二选一:

  1. 直接禁用发布裁剪
    修改Dockerfile中的dotnet publish命令,移除/p:PublishTrimmed=true参数:
RUN dotnet publish -c Release --self-contained true -o /out
  1. 保留裁剪并添加豁免配置
    在项目根目录创建TrimmerRoots.xml文件,内容如下:
<linker>
  <assembly fullname="MediatR" />
  <assembly fullname="MediatR.Extensions.Microsoft.DependencyInjection" />
</linker>

然后在项目的.csproj文件中添加引用:

<ItemGroup>
  <TrimmerRootDescriptor Include="TrimmerRoots.xml" />
</ItemGroup>

此配置会告诉裁剪工具保留MediatR相关的必要类型,避免构造函数无法解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:35:09