AutoMapper IValueResolver:无法访问已处置的对象。对象名称:'IServiceProvider'
AutoMapper IValueResolver: Cannot access a disposed object. Object name: 'IServiceProvider'
我想用AutoMapper中的IValueResolver映射两个class,一个值会从HttpRequest Context中取,所以我想用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";
}
内部启动 class 我把这个:
services.AddAutoMapper(typeof(Startup));
但每次我为 MemberID 映射它们时都会抛出错误,说 IServiceProvider 已被处置。
那么如何使这些工作?我尝试在启动时注入这个 SpecialResolver 但也没有用。顺便说一句,我使用的是.net core 3.0
我坚信您的代码中某处出现了错误,因此出现了问题。在我这边,一切正常。根据您的问题和评论,我试图重新表达您正在尝试做的事情。肯定会有或多或少的差异,但是你应该能够把握思路,自己去实现。
我从一个映射配置文件开始,我在其中明确指定 HttpContextValueResolver
对 MemberId
属性 或 ViewModel
class 的用法:
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();
}
请注意,在仅传递一种类型(Startup)时注册 AutoMapper,要求所有映射配置文件都需要与 Startup 在同一程序集(项目)中。对于多个程序集中的映射配置文件,您需要使用 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; }
}
我想用AutoMapper中的IValueResolver映射两个class,一个值会从HttpRequest Context中取,所以我想用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";
}
内部启动 class 我把这个:
services.AddAutoMapper(typeof(Startup));
但每次我为 MemberID 映射它们时都会抛出错误,说 IServiceProvider 已被处置。 那么如何使这些工作?我尝试在启动时注入这个 SpecialResolver 但也没有用。顺便说一句,我使用的是.net core 3.0
我坚信您的代码中某处出现了错误,因此出现了问题。在我这边,一切正常。根据您的问题和评论,我试图重新表达您正在尝试做的事情。肯定会有或多或少的差异,但是你应该能够把握思路,自己去实现。
我从一个映射配置文件开始,我在其中明确指定 HttpContextValueResolver
对 MemberId
属性 或 ViewModel
class 的用法:
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();
}
请注意,在仅传递一种类型(Startup)时注册 AutoMapper,要求所有映射配置文件都需要与 Startup 在同一程序集(项目)中。对于多个程序集中的映射配置文件,您需要使用 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; }
}