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

ASP.NET Core中StructureMap与AutoMapper解析器依赖注入异常问题

解决AutoMapper解析器无法实例化的问题

我帮你排查下这个问题!你遇到的AutoMapperMappingException: Cannot create an instance of type AutomapperProfiles.UserRolesResolver异常,核心原因是AutoMapper没有拿到正确的依赖注入容器来解析你的自定义解析器,结合你用StructureMap作为DI容器的场景,咱们一步步来解决:

1. 确保解析器和依赖服务都注册到StructureMap

StructureMap不会自动识别所有自定义类型,你得确保UserRolesResolver和它依赖的AppUserManager都被正确注册到容器里。推荐用扫描程序集的方式批量注册,省得手动逐个添加:

// 在StructureMap的配置代码中
container.Configure(config =>
{
    config.Scan(scan =>
    {
        scan.TheCallingAssembly(); // 扫描当前程序集
        scan.WithDefaultConventions(); // 注册所有符合默认约定的类型
        scan.AddAllTypesOf<IValueResolver>(); // 自动注册所有实现IValueResolver的类,包括你的UserRolesResolver
    });

    // 如果AppUserManager是自定义服务,确保它也被注册:
    config.For<AppUserManager>().Use<AppUserManager>();
});

2. 让AutoMapper用StructureMap容器构造服务

你之前在AddAutoMapper里用了x.ConstructServicesUsing(type=> ServiceProvider.GetRequiredService(type)),但这里的ServiceProvider大概率是ASP.NET Core默认的DI容器,而非你配置的StructureMap容器,所以AutoMapper找不到解析器的实例。

正确的做法是,在StructureMap容器初始化完成后,给AutoMapper指定用StructureMap来构造服务:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // 先添加AutoMapper基础服务
    services.AddAutoMapper(typeof(OrderProfile).Assembly);

    // 初始化StructureMap容器
    var container = new Container();
    container.Configure(config =>
    {
        // 上面的注册代码...
        config.Populate(services); // 把ASP.NET Core的服务导入到StructureMap
    });

    // 关键:让AutoMapper使用StructureMap容器来解析服务
    var mapperConfig = container.GetInstance<MapperConfiguration>();
    mapperConfig.ConstructServicesUsing(type => container.GetInstance(type));

    // 返回StructureMap的ServiceProvider替换默认DI
    return container.GetInstance<IServiceProvider>();
}

3. 验证映射配置是否正确

最后检查你的Profile中是否正确引用了这个解析器,比如:

public class UserProfile : Profile
{
    public UserProfile()
    {
        CreateMap<User, CurrentUserViewModel>()
            .ForMember(dest => dest.Roles, opt => opt.MapFrom<UserRolesResolver>());
    }
}

额外优化建议

你在解析器里用AsyncHelpers.RunSync来调用异步方法,其实AutoMapper支持异步解析器IAsyncValueResolver,可以避免同步阻塞:

public class UserRolesResolver : IAsyncValueResolver<User, CurrentUserViewModel, List<string>>
{
    private readonly AppUserManager _appUserManager;

    public UserRolesResolver(AppUserManager appUserManager)
    {
        _appUserManager = appUserManager;
    }

    public async Task<List<string>> ResolveAsync(User source, CurrentUserViewModel destination, List<string> destMember, ResolutionContext context)
    {
        var roles = await _appUserManager.GetRolesAsync(source);
        destination.Roles = roles.ToList();
        return destination.Roles;
    }
}

然后在映射时使用ResolveUsingAsync:

CreateMap<User, CurrentUserViewModel>()
    .ForMember(dest => dest.Roles, opt => opt.ResolveUsingAsync<UserRolesResolver>());

这样代码更符合异步编程的最佳实践~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:15:17