在automapper中没有为此对象定义无参数构造函数

Sho*_*hoe 2 c# asp.net automapper asp.net-core

我有以下值解析器:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

此解析程序尝试获取Student此模型的属性:

public class LessonResponse
{
    public string Id { get; set; }

    public UserResponse Student { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但是就行了:

var result = Mapper.Map<UserResponse>(user);
Run Code Online (Sandbox Code Playgroud)

我明白了:

{System.MissingMethodException:没有为此对象定义无参数构造函数.System.Activator.CreateInstance的System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean&canBeCached,RuntimeMethodHandleInternal&ctor)中的System.RuntimeType.CreateInstanceSlow(Boolean publicOnly,Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&stackMark)(Type type,Boolean 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; }
}
Run Code Online (Sandbox Code Playgroud)

但它是可构建的,所以我做错了什么?


额外

映射配置文件如下:

public class MappingProfile : Profile 
{
    public MappingProfile() {
        CreateMap<Lesson, LessonResponse>()                
            .ForMember(
                dest => dest.Student,
                opts => opts.ResolveUsing<StudentResolver>());

    }
}
Run Code Online (Sandbox Code Playgroud)

而用户的映射是:

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>());
    }
}
Run Code Online (Sandbox Code Playgroud)

布尔解析器类似于:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Tas*_*key 9

如果其他人做了与我相同的事情,这就是我的问题:

public sealed class MyProfile : Profile
{
    MyProfile()
    {
        // Configuration
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我忘记将构造函数标记为public. 一旦我将其标记为公开,一切就都正常了。


neu*_*t47 8

我因为我的注意力不集中的同样的问题...我生成由Visual Studio快速提示默认的构造函数从继承的类Profile这是protected不是public.可能这会对某人有所帮助,因为我花了几个小时才弄明白


pen*_*han 5

很抱歉自昨天以来下班后筋疲力尽,回复时间很长。

我能够复制您的问题。您有2个选择:

第一种选择解决您StudentResolver的问题DbContext

CreateMap<Lesson, LessonResponse>()
            .ForMember(
                dest => dest.Student,
                opts => opts.ResolveUsing(new StudentResolver(ApplicationDbContext.Create())));
Run Code Online (Sandbox Code Playgroud)

第二个选项,配置您的映射器配置ConstructServicesUsing。就我而言,我正在使用简单注入器进行测试。

Mapper.Initialize(cfg =>
        {
            cfg.ConstructServicesUsing(type => container.GetInstance(typeof(StudentResolver)));
            cfg.AddProfile<MappingProfile>();
        });
Run Code Online (Sandbox Code Playgroud)

在测试中,我抛出了一个错误 var lessonResponse = Mapper.Map<LessonResponse>(lesson);

所以,如果你是抛出Mapper.Map<UserResponse>(user);你可能要为ConstructService IsAdminResolverIsInstructorResolverIsClientResolver

  • @penleychan,当[存在](https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/)时,这似乎是在重新发明轮子,而且它非常复杂并且违背了目的。 (2认同)