web-dev-qa-db-fra.com

Comment injecter un service dans la classe de profil AutoMapper

J'ai besoin d'utiliser une couche de service dans la classe de profil AutoMapper dans ASP.NET Core mais quand j'injecte du service dans le constructeur ça ne marche pas. Par exemple:

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

Et dans Startup Classe:

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

Comment faire?

13
M.Shakeri

Pour résoudre votre problème, il vous suffit de câbler IUserManager dans DI et de vous assurer que la dépendance UserProfile est résolue.

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

Cela dit, j'essaierais probablement de conserver une seule responsabilité par classe et de ne pas injecter de services dans les profils de mappage. Vous pouvez à la place remplir vos objets juste avant le mappage. De cette façon, il pourrait également être plus facile de tester les unités.

27
Ignas

Il est préférable d'utiliser IValueResolver personnalisé à cet effet car il prend entièrement en charge l'intégration IServiceCollection (en utilisant AutoMapper.Extensions.Microsoft.DependencyInjection ).

Vous devrez peut-être implémenter un résolveur de valeurs personnalisé:

public class UserViewModelValueResolver: IValueResolver<...>
{
    public readonly IUserManager userManager;
    public UserViewModelValueResolver(IUserManager userManager)
    {
        this.userManager = userManager;
    }
    ...
}

Et l'inscription dans les services peut être réduite à:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddSingleton<IUserManager, UserManager>();
}

Ensuite, vous pouvez obtenir une instance de mappeur dans un contrôleur en injectant IMapper via un constructeur.

Basé sur: AutoMapper: Gestion des dépendances de profil à l'aide de résolveurs de valeurs personnalisés - Tech Net

7
Pavel Sapehin