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?
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.
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.