我有以下值解析器:
public class StudentResolver : IValueResolver<Lesson, LessonResponse, UserResponse>
{
private readonly ApplicationDbContext _dbContext;
public StudentResolver(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public UserResponse Resolve(
Lesson lesson,
LessonResponse response,
UserResponse member,
ResolutionContext context)
{
var user = _dbContext.Users
.Where(x => x.Id == lesson.StudentId)
.FirstOrDefault();
if (user == null)
return null;
var result = Mapper.Map<UserResponse>(user); // this line triggers a "no parameterless constructor", why?
return result;
}
}
此解析程序尝试获取此模型的Student
属性:
public class LessonResponse
{
public string Id { get; set; }
public UserResponse Student { get; set; }
}
但是就行了:
var result = Mapper.Map<UserResponse>(user);
我明白了:
{System.MissingMethodException:没有为此对象定义无参数构造函数。 System.Activator.CreateInstance的System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean&amp; canBeCached,RuntimeMethodHandleInternal&amp; ctor)处于System.RuntimeType.CreateInstanceSlow(Boolean publicOnly,Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&amp; stackMark)中的类型类型,Auto NonPublic)在AutoMapper.MappingOperationOptions`2.CreateInstanceT}的System.Activator.CreateInstance(Type type)中。
该表达式中唯一应该创建的类型是UserResponse
,其定义如下:
public class UserResponse
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Picture { get; set; }
public string X { get; set; }
public bool IsAdmin { get; set; }
public bool IsClient { get; set; }
public bool IsInstructor { get; set; }
}
但它是可构造的,所以我做错了什么?
映射配置文件如下:
public class MappingProfile : Profile
{
public MappingProfile() {
CreateMap<Lesson, LessonResponse>()
.ForMember(
dest => dest.Student,
opts => opts.ResolveUsing<StudentResolver>());
}
}
用户的映射是:
public class MappingProfile : Profile
{
public MappingProfile() {
CreateMap<ApplicationUser, UserResponse>()
.ForMember(
dest => dest.FullName,
opts => opts.MapFrom(
origin => origin.FirstName + " " + origin.LastName))
.ForMember(
dest => dest.IsAdmin,
opts => opts.ResolveUsing<IsAdminResolver>())
.ForMember(
dest => dest.IsInstructor,
opts => opts.ResolveUsing<IsInstructorResolver>())
.ForMember(
dest => dest.IsClient,
opts => opts.ResolveUsing<IsClientResolver>());
}
}
布尔解析器类似于:
public class IsAdminResolver : IValueResolver<ApplicationUser, UserResponse, bool>
{
private readonly UserManager<ApplicationUser> _userManager;
public IsAdminResolver(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public bool Resolve(ApplicationUser user, UserResponse response, bool member, ResolutionContext context)
{
return _userManager.IsInRoleAsync(user, "Admin").Result;
}
}
答案 0 :(得分:7)
由于我的疏忽,我遇到了同样的问题...我通过Visual Studio快速提示默认构造函数为继承自Profile
的类protected
而不是public
生成。可能这会对某人有所帮助,因为我花了几个小时来弄明白
答案 1 :(得分:4)
我能够复制你的问题。您有两个选择:
第一个选项使用StudentResolver
解析您的DbContext
:
CreateMap<Lesson, LessonResponse>()
.ForMember(
dest => dest.Student,
opts => opts.ResolveUsing(new StudentResolver(ApplicationDbContext.Create())));
第二个选项,配置您的映射器配置ConstructServicesUsing
。就我而言,我使用Simple Injector来测试。
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => container.GetInstance(typeof(StudentResolver)));
cfg.AddProfile<MappingProfile>();
});
对于我的测试,我收到了错误var lessonResponse = Mapper.Map<LessonResponse>(lesson);
因此,如果您被Mapper.Map<UserResponse>(user);
投掷,则可能需要IsAdminResolver
,IsInstructorResolver
和IsClientResolver
答案 2 :(得分:1)
如果其他人做我做的同样的事情,这就是我的问题:
public sealed class MyProfile : Profile
{
MyProfile()
{
// Configuration
}
}
如您所见,我忘记将构造函数标记为public
。将其标记为公开后,一切正常。
答案 3 :(得分:1)
我们遇到了同样的问题,原来这行代码应该是我们启动时的最后一行代码
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
此外,在加载autofac模块时,我们将本地注册移至最后一行,以便它们覆盖nuget软件包中的注册。
请注意,删除构造函数不是解决方案,因此请尝试解决如上所述的依赖项注入问题。
答案 4 :(得分:0)
就我而言,我有以下映射器:
public class Mapper : Profile
{
public Mapper(IConfiguration configuration)
{
}
}
修复程序是从构造函数中删除配置参数(从而使其成为无参数的构造函数)。