5

I'm trying to register AutoMapper 5.1.1 with CastleWindsor, but I don't know, where to properly call Mapper.Initialize().

AutoMapper profile:

namespace AutoMapper_DI.Mappings
{
    public class WebMappingProfile : Profile
    {        
        public WebMappingProfile()
        {
          CreateMap<Person, PersonDTO>();            
        }
    }
}

Castle Windsor registration:

class MainInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {            
        container.AddFacility<TypedFactoryFacility>();

        container.Register(Component.For<IMapper>().UsingFactoryMethod(x =>
        {
            return new MapperConfiguration(c =>
            {
                c.AddProfile<WebMappingProfile>();
            }).CreateMapper();
        }));

        container.Register(Component.For<MainClass>());
    }
}

And then when I use _mapper I got Mapper not initialized exception:

class MainClass
{
    private readonly IMapper _mapper;

    public MainClass(IMapper mapper)
    {
        _mapper = mapper;
    }

    public void Start()
    {            
        Person p = new Person
        {
            Name = "Somebody",
            Surname = "Nobody",
            Birth = new DateTime(1984, 06, 18)
        };            
        var personDTO = Mapper.Map<Person, PersonDTO>(p);

    }

}

Thanks for any advices.

Michal
  • 803
  • 2
  • 9
  • 26
  • Have you considered creating the mapper configuration separately and registering it as an "instance" with `Component.For().Instance(mapper);` – stuartd Sep 23 '16 at 14:17

2 Answers2

5

So, code above is working. Problem was, that I'm an idiot. Because I should not calling Mapper.Map, but _mapper.Map.

Michal
  • 803
  • 2
  • 9
  • 26
3

For those who are using Automapper 9.0 with Castle Windsor (my version is 3.2.0) using container. I created a file where I register my model with Dtos. 1. AutoMapperProfile.cs

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        //Register all model with Dtos here
        CreateMap<UserMenuReadModel, UserMenuDto>();
    }        
}

2. I have AutoMapperInstall.cs as Installer

public class AutoMapperInstall : Castle.MicroKernel.Registration.IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Castle.MicroKernel.Registration.Component.For<IMapper>().UsingFactoryMethod(factory =>
        {
            return new MapperConfiguration(map =>
            {
                map.AddProfile<AutoMapperProfile>();

            }).CreateMapper();
        }));
    }
}

3. I register all of my installer on BootstrapConfig.cs

public class BootstrapConfig
{
    public static void Register(IWindsorContainer container)
    {
        GlobalConfiguration.Configuration.Services.Replace(
            typeof(IHttpControllerActivator),
            new WindsorCompositionRoot(container));

        container.Install(               
            new DomainModelLayerInstall(),               
            new AutoMapperInstall()
        );
    }
}
  1. Now I'm good to go. Just make an instance of mapper through constructor and use it.

     readonly IMapper mapper;
     public UserMenuService(IMapper mapper)
     {          
         this.mapper = mapper;
      }
    
  2. When you want to return the Dto, simply use

    return mapper.Map<IEnumerable<UserMenuReadModel>, List<UserMenuDto>>(result);
    
  3. Last but not least, register IOC bootstrap config on global.asax

        container = new WindsorContainer();
        BootstrapConfig.Register(this.container)
    

Hope this helps someone using new version of AutoMapper with Castle Windsor. Feel free to comment with criticisms or suggestions.

curious.netter
  • 774
  • 10
  • 16