AutoMapper IValueResolver:无法访问已处置的对象。对象名称:“ IServiceProvider”

时间:2019-12-20 09:42:59

标签: c# asp.net-core-mvc automapper

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

CreateMap<Dto, ViewModel>().ForMember(x=>x.MemberID, opt=>opt.Mapfrom<SpecialResolver>())

而且解析器很简单

public string Resolve(ViewModel viewModel, Dto dto, string destMember, ResolutionContext context)
{
  return "test";
}

在启动类内部,我这样:

services.AddAutoMapper(typeof(Startup));

但是每次我将它们映射为MemberID时都会抛出错误,提示已丢弃IServiceProvider。 那么如何使这些工作呢?我尝试在启动时注入此SpecialResolver,但也无法正常工作。顺便说一句,我使用的是.net core 3.0

1 个答案:

答案 0 :(得分:4)

我坚信错误会潜入您的代码中,从而引发问题。在我这边,一切正常。根据您的问题和评论,我尝试将您的工作保密。肯定会有或多或少的差异,但是您应该能够掌握这个想法并将其自己付诸实践。

我从映射配置文件开始,在这里我为HttpContextValueResolver类的MemberId属性显式指定ViewModel的用法:

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

然后是值解析器:

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;
    }
}

为了在控制器外部访问HttpContext,我使用了专用的IHttpContextAccessor服务。在docs中详细了解它。

它不是自动可用的,因此我需要在Startup中将其与AutoMapper一起注册:

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

    services.AddAutoMapper(typeof(Startup));

    services.AddHttpContextAccessor();
}

请注意,在仅传递一种类型(启动)的情况下注册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();
    }
}

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

public class Dto
{
    public string MemberID { get; set; }
}
public class ViewModel
{
    public string MemberId { get; set; }
}