views:

799

answers:

1
+3  Q: 

Inject AutoMapper

I have been working on injecting AutoMapper into controllers. I like the implementation of Code Camp Server. It creates a wrapper around AutoMapper's IMappingEngine. The dependency injection is done using StructureMap. But I need to use Castle Windsor for my project. So, how do we implement the following dependency injection and set-up using Windsor? I am not looking for line-by-line equivalent implementation in Castle Windsor. If you want to do that, please feel free. Instead, what is Windsor equivalent of StructureMap's Registry and Profile? I need Profile to define CreateMap<> like the following.

Thanks.

Meeting controller:

public MeetingController(IMeetingMapper meetingMapper, ...)

Meeting Mapper:

public class MeetingMapper : IMeetingMapper
{

    private readonly IMappingEngine _mappingEngine;

    public MeetingMapper(IMappingEngine mappingEngine)
    {
      _mappingEngine = mappingEngine;
    }

    public MeetingInput Map(Meeting model)
    {
        return _mappingEngine.Map<Meeting, MeetingInput>(model);    
    }

    ......
}

Auto Mapper Registry:

public class AutoMapperRegistry : Registry
{

    public AutoMapperRegistry()
    {
        ForRequestedType<IMappingEngine>().TheDefault.Is.ConstructedBy(() => Mapper.Engine);
    }
}

Meeting Mapper Profile:

public class MeetingMapperProfile : Profile
{

    public static Func<Type, object> CreateDependencyCallback = (type) => Activator.CreateInstance(type);

    public T CreateDependency<T>()
    {
        return (T)CreateDependencyCallback(typeof(T));
    }

    protected override void Configure()
    {
        Mapper.CreateMap<MeetingInput, Meeting>().ConstructUsing(
            input => CreateDependency<IMeetingRepository>().GetById(input.Id) ?? new Meeting())

       .ForMember(x => x.UserGroup, o => o.MapFrom(x => x.UserGroupId))
       .ForMember(x => x.Address, o => o.Ignore())
       .ForMember(x => x.City, o => o.Ignore())
       .ForMember(x => x.Region, o => o.Ignore())
       .ForMember(x => x.PostalCode, o => o.Ignore())
       .ForMember(x => x.ChangeAuditInfo, o => o.Ignore());
    }
}
+1  A: 

you mean how do you register it in Windsor?

you may have to register FactorySupportFacility fist... I have no way of checking at this moment.

container.AddFacility<FactorySupportFacility>();

and then

container.Register(Component.For<IMappingEngine>().UsingFactoryMethod(()=>
            Mapper.Engine));
Krzysztof Koźmic
What about the Profile part in StructureMap? Mapper.CreateMap<x, y>.ForMember() is called from MeetingMapperProfile class. How to do that in Castle Windsor? Thanks.
Roger
what is this Profile? What does it do? If you mean just the Configure method, than you do it, where you register your components to the container, It has no dependency on the container whatsoever AFAICS
Krzysztof Koźmic
Profile in StructureMap is the ability to switch out different concrete implementations of a service (i.e. class) at runtime depending on the context in which they are used. But if you look at the Meeting profile, it is not actually doing that. The Mapper.CreateMap<>.ForMember(...) in the Meeting Profile has to be called before the MeetingMapper calls _mappingEngine.Map(). I am thinking about creating a Facility in Windsor to do what the Meeting Profile is doing right now. What do you think? Thanks.
Roger

related questions