noir
noir

Reputation: 566

Castle Windsor does not resolve AutoMapper profiles after update

Everything was working fine until I updated with NuGet the references for CastleWinsor and AutoMapper to their latest versions: Castle.Windsor.3.0.0.4001 and AutoMapper.2.0.0.

I have a list of AutoMapper profiles in the same assembly as the AutoMapperInstaller : IWindsorInstaller. They are in diferent namespaces, but this should not matter, right?

Here is a profile example:

namespace FieldService.Web.Mappings
{
 public class RoleMappings : Profile
 {
    protected override void Configure()
    {
        AutoMapper.Mapper.CreateMap<RoleModel, Role>()
            .ConstructUsing((role) => new Role() { Permissions = new List<Permission>() })
            .ForMember(m => m.Permissions, o => o.MapFrom(src => src.Permissions.Where(p => p.Selected == true)));
    }
 }
}

Here is the AutoMapperInstaller

namespace FieldService.Web.Infrastructure.IOC
{
 public class AutoMapperInstaller : IWindsorInstaller
 {
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        Mapper.Initialize(x => x.ConstructServicesUsing(container.Resolve));

        RegisterProfilesAndResolvers(container);
        RegisterMapperEngine(container);
    }

    private void RegisterMapperEngine(IWindsorContainer container)
    {
        container.Register(
            Component.For<IMappingEngine>().Instance(Mapper.Engine)
        );
    }

    private void RegisterProfilesAndResolvers(IWindsorContainer container)
    {
        // register value resolvers
        container.Register(AllTypes.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());

        // register profiles
        container.Register(AllTypes.FromThisAssembly().BasedOn<Profile>());
        var profiles = container.ResolveAll<Profile>();

        foreach (var profile in profiles)
            Mapper.AddProfile(profile);
    }
 }
}

In Global.asax I have the method BootstrapContainer which I call from Application_Start method:

private static readonly IWindsorContainer container = new WindsorContainer();

    public IWindsorContainer Container
    {
        get { return container; }
    }

    private static void BootstrapContainer()
    {
        container.Install(FromAssembly.This());
    }

The exception I get is: Trying to map xxx to yyyModel. Missing type map configuration or unsupported mapping. Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.

I debugged the installer and I think this line Container.Register(AllTypes.FromThisAssembly().BasedOn<Profile>()); is not working anymore.

If I try to resolve the profiles (next line) it returns 0 profiles.

I am not an expert with these two tools, and I am not sure this is the best method to initialize AutoMapper with Windsor but it worked until now.

Any idea why this is not working anymore?

Upvotes: 2

Views: 1779

Answers (2)

Simple Code
Simple Code

Reputation: 2574

For me this code worked :

public class AutoMapperInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            // Register all mapper profiles
            container.Register(
                Classes.FromAssemblyInThisApplication(GetType().Assembly)
                .BasedOn<Profile>().WithServiceBase());
                
            // Register IConfigurationProvider with all registered profiles
            container.Register(Component.For<IConfigurationProvider>().UsingFactoryMethod(kernel =>
            {
                return new MapperConfiguration(configuration =>
                {
                    kernel.ResolveAll<Profile>().ToList().ForEach(configuration.AddProfile);
                });
            }).LifestyleSingleton());
            
            // Register IMapper with registered IConfigurationProvider
            container.Register(
                Component.For<IMapper>().UsingFactoryMethod(kernel =>
                    new Mapper(kernel.Resolve<IConfigurationProvider>(), kernel.Resolve)));
        }
}

Upvotes: 0

Krzysztof Kozmic
Krzysztof Kozmic

Reputation: 27374

This is a known and documented breaking change in Windsor (see breakingchanges.txt for details).

In short, if you're resolving your profiles as Profile you need to register them as Profile.

Container.Register(AllTypes.FromThisAssembly().BasedOn<Profile>().WithServiceBase());

Upvotes: 4

Related Questions