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 AutoMapperReg开发者_如何学JAVAistry : 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());
}
}
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));
I'm not familiar with Castle Windsor but here is the StructureMap syntax. You would need to set up your registry a little different. Instead of setting the IMappingEngine to Mapper.Engine, you will have to do configure a few more interfaces. It's a little more work but this will allow you to set the profile as part of registration.
public AutoMapperRegistry()
{
//type mapping
For<ConfigurationStore>()
.Singleton()
.Use(ctx =>
{
ITypeMapFactory factory = ctx.GetInstance<ITypeMapFactory>();
ConfigurationStore store
= new ConfigurationStore(factory, MapperRegistry.AllMappers());
IConfiguration cfg = store;
//Here's where you load your profile
cfg.AddProfile<MeetingMapperProfile>();
store.AssertConfigurationIsValid();
return store;
});
For<IConfigurationProvider>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<IConfiguration>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
For<IMappingEngine>().Use<MappingEngine>();
For<ITypeMapFactory>().Use<TypeMapFactory>();
}
I realize this is a bit old, but I use Castle Windsor, and it's been fairly easy to get AutoMapper profiles loaded using an installer:
using System.Linq;
using System.Reflection;
using AutoMapper;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace YourNamespace
{
public class AutoMapperInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
Mapper.Initialize(m => m.ConstructServicesUsing(container.Resolve));
container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());
container.Register(Types.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
var profiles = container.ResolveAll<Profile>();
profiles.ToList().ForEach(p => Mapper.AddProfile(p));
container.Register(Component.For<IMappingEngine>().Instance(Mapper.Engine));
}
}
}
This installer would pick up the MeetingMapperProfile
shown in the question, or any other class based on AutoMapper's Profile
.
精彩评论