AutoMapper IValueResolver:无法访问已处理的对象。对象名称:'IServiceProvider'

Bei*_*ZHU 1 c# automapper asp.net-core-mvc

我想在 AutoMapper 中使用 IValueResolver 来映射两个类,并且将从 HttpRequest Context 中获取一个值,所以我想使用 IValueResolver

CreateMap<Dto, ViewModel>().ForMember(x=>x.MemberID, opt=>opt.Mapfrom<SpecialResolver>())
Run Code Online (Sandbox Code Playgroud)

和解析器很简单

public string Resolve(ViewModel viewModel, Dto dto, string destMember, ResolutionContext context)
{
  return "test";
}
Run Code Online (Sandbox Code Playgroud)

在启动类中,我把这个:

services.AddAutoMapper(typeof(Startup));
Run Code Online (Sandbox Code Playgroud)

但是每次我将它们映射到 MemberID 时都会抛出错误,说 IServiceProvider 已被处理。那么如何使这些工作?我尝试在启动时注入这个 SpecialResolver 但也没有工作。顺便说一句,我使用 .net core 3.0

Pro*_*log 5

我坚信一个错误已经潜入您的代码中的某个地方,从而导致您的问题。在我这边,一切正常。根据您的问题和评论,我试图重新定义您正在尝试做的事情。它肯定会或多或少地有所不同,但您应该能够掌握这个想法并自行完成。

我从一个映射配置文件开始,我在其中明确指定了HttpContextValueResolverfor类MemberId属性的用法ViewModel

public class MyMappingProfile : Profile
{
    public MyMappingProfile()
    {
        CreateMap<Dto, ViewModel>()
            .ForMember(x => x.MemberId, opt => opt.MapFrom<HttpContextValueResolver>());
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是值解析器:

public class HttpContextValueResolver : IValueResolver<Dto, ViewModel, string>
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public HttpContextValueResolver(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public string Resolve(Dto source, ViewModel destination, string destMember, ResolutionContext context)
    {
        // Obtain whatever you need from HTTP context.
        // Warning! HTTP context may be null.

        return _httpContextAccessor.HttpContext?.Request.Path;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了在控制器之外访问 HttpContext,我使用了一个专门用于该目的的服务,称为IHttpContextAccessor. 在文档中阅读更多关于它的信息。

它不是自动可用的,所以我需要将它Startup与 AutoMapper 一起注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddAutoMapper(typeof(Startup));

    services.AddHttpContextAccessor();
}
Run Code Online (Sandbox Code Playgroud)

请注意,在仅传递一种类型(启动)时注册 AutoMapper,要求所有映射配置文件都需要与启动在同一个程序集(项目)中。对于多个程序集中的映射配置文件,您需要使用合适的AddAutoMapper()方法重载来指定这些程序集或类型。

最后在示例控制器中使用:

public class HomeController : Controller
{
    private readonly IMapper mapper;

    public HomeController(IMapper mapper)
    {
        this.mapper = mapper;
    }

    public IActionResult Index()
    {
        var source = new Dto
        {
            MemberID = "123",
        };
        var result = mapper.Map<ViewModel>(source);

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我使用的 dto 和视图模型:

public class Dto
{
    public string MemberID { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
public class ViewModel
{
    public string MemberId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)