Search code examples
c#automapperunity-container

How can I make Unity resolve models that AutoMapper creates when mapping?


I have e.g. the following code that queries a list of DTOs, and maps that to a list of viewmodels. I would like to have my container resolve these viewmodels, instead of AutoMapper simply instantiating them without any injection.

using (var db = new AppDbContext())
{
    var types = await db.ApptTypes
        .Where(t => t.BranchId == branchId && (includeDeleted || !t.IsDeleted))
        .Include(e => e.CreatedBy)
        .Include(e => e.CreatedAt)
        .Include(e => e.Org)
        .Include(e => e.Branch)
        .ToListAsync(cancellationToken);
    return Mapper.Map<IEnumerable<ApptTypeDetailViewModel>>(types);
}

Solution

  • Thanks to this answer, I have found a neat and fairly reliable way of achieving what I want. The main process looks like this:

    class Program
    {
        private static IUnityContainer _container;
        static void Main(string[] args)
        {
            var boot = new Bootstrapper();
            boot.Run();
            _container = boot.Container;
    
            InitMaps(_container);
    
            var dto = new Dto {Id = 418, Name = "Abrahadabra"};
            var model = Mapper.Map<ViewModel>(dto);
        }
    
        private static void InitMaps(IUnityContainer container)
        {
            Mapper.Initialize(cfg =>
            {
                cfg.CreateMap<Dto, ViewModel>()
                    .ConstructUsing(f => UnityObjectFactoty.GetInstance<ViewModel>(container));
            });
        }
    }
    

    And the factory:

    class UnityObjectFactoty
    {
        public static TObject GetInstance<TObject>(IUnityContainer container)
        {
            return container.Resolve<TObject>();          
        }
    }
    

    Where the viewmodel is:

    public class ViewModel
    {
        public ViewModel(IService service)
        {
            _service = service;
        }
    
        private IService _service;
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    All that remains is to provide ctor parameters not resolved by the container, but that is not a requirement in my use case of this pattern.