如何在AutoMapper配置文件类中注入服务

M.S*_*eri 14 automapper asp.net-core

我需要在AutoMapper配置文件类中使用服务层,ASP.NET Core但是当我在构造函数中注入服务时,它不起作用.例如:

public class UserProfile : Profile
{
    private readonly IUserManager _userManager;

    public UserProfile(IUserManager userManager)
    {
        _userManager = userManager;

        CreateMap<User, UserViewModel>()
           .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"));
    }
}
Run Code Online (Sandbox Code Playgroud)

Startup课堂上:

 public class Startup
{
    public IConfigurationRoot Configuration { set; get; }

    public Startup(IHostingEnvironment env)
    {
       //some code
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
        services.AddMvc();
        services.AddScoped<IUsersPhotoService, UsersPhotoService>();
        services.AddAutoMapper(typeof(UserProfile));
    }
}
Run Code Online (Sandbox Code Playgroud)

怎么做?

Ign*_*nas 29

要解决您的问题,您只需要连接IUserManagerDI,并确保UserProfile依赖性得到解决.

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSingleton<IUserManager, UserManager>();
    services.AddSingleton(provider => new MapperConfiguration(cfg =>
    {
        cfg.AddProfile(new UserProfile(provider.GetService<IUserManager>()));
    }).CreateMapper());
}
Run Code Online (Sandbox Code Playgroud)

说到这一点,我可能会尝试保持每个类的单一责任,而不是将任何服务注入到映射配置文件中.您可以在映射之前填充对象.这样,单元测试也可能更容易.

  • 有没有什么方法可以使它更方便(例如容器集成),而不是就容器的生命周期调用 `provider.GetService&lt;T&gt;()`? (2认同)

Pav*_*hin 7

为此,最好使用自定义IValueResolver,因为它完全支持IServiceCollection集成(使用AutoMapper.Extensions.Microsoft.DependencyInjection)。

您可能需要实现自定义值解析器:

public class UserViewModelValueResolver: IValueResolver<...>
{
    public readonly IUserManager userManager;
    public UserViewModelValueResolver(IUserManager userManager)
    {
        this.userManager = userManager;
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

服务中的注册可以减少为:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSingleton<IUserManager, UserManager>();
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以IMapper通过构造函数进行注入,从而在控制器内获取一个mapper实例。

基于:AutoMapper:使用自定义值解析器处理配置文件依赖性-Tech Net

  • 这种方法的问题是 LINQ 提供程序无法翻译它。根据 AutoMapper 文档,`ResolveUsing` 不是受支持的映射选项。如果你尝试,AutoMapper 只会抛出 `System.Exception: Can't resolve this to Queryable Expression` (4认同)