2009-11-12 20 views
8

Pracowałem nad wtryskiem AutoMappera do kontrolerów. Podoba mi się wdrożenie Code Camp Server. Tworzy owijkę wokół narzędzia IMappingEngine programu AutoMapper. Zastrzyk zależności jest wykonywany za pomocą StructureMap. Ale muszę użyć Castle Windsor do mojego projektu. W jaki sposób możemy zaimplementować następującą iniekcję zależności i konfigurację za pomocą Windsor? Nie szukam ekwiwalentnej implementacji liniowej w Castle Windsor. Jeśli chcesz to zrobić, nie krępuj się. Zamiast tego, co jest odpowiednikiem Windsor w rejestrze i profilu StructureMap? Potrzebuję profilu do zdefiniowania CreateMap <> jak poniżej.Injection AutoMapper

Dzięki.

kontroler Zgromadzenie:

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 Profil:

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()); 
    } 
} 

Odpowiedz

3

to znaczy w jaki sposób zarejestrować go w Windsor?

być może trzeba będzie zarejestrować pięść FactorySupportFacility ... Nie mam możliwości sprawdzenia w tej chwili.

container.AddFacility<FactorySupportFacility>(); 

a następnie

container.Register(Component.For<IMappingEngine>().UsingFactoryMethod(()=> 
      Mapper.Engine)); 
+0

Co z częścią Profile w StructureMap? Mapper.CreateMap .ForMember() jest wywoływana z klasy MeetingMapperProfile. Jak to zrobić w Castle Windsor? Dzięki. – Roger

+0

co to jest profil? Co to robi? Jeśli masz na myśli tylko metodę Configure, niż to robisz, gdzie rejestrujesz swoje komponenty do kontenera, nie ma zależności od kontenera, w jakiejkolwiek strukturze AFAICS –

+0

Profil w StructureMap to możliwość przełączania różnych konkretnych implementacji usługi (np.) w czasie wykonywania w zależności od kontekstu, w którym są używane. Ale jeśli spojrzysz na profil Spotkania, tak naprawdę to nie robi. Mapper.CreateMap <>. ForMember (...) w profilu spotkania musi zostać wywołany przed wywołaniem MeetingMapper _mappingEngine.Map().Zastanawiam się nad utworzeniem obiektu w Windsor, aby robić to, co robi teraz profil spotkania. Co myślisz? Dzięki. – Roger

2

nie jestem zaznajomiony z zamku Windsor, ale tutaj jest składnia StructureMap. Będziesz musiał ustawić swój rejestr trochę inaczej. Zamiast ustawiać IMappingEngine na Mapper.Engine, będziesz musiał skonfigurować kilka dodatkowych interfejsów. To trochę więcej pracy, ale pozwoli ci ustawić profil jako część rejestracji.

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>(); 
} 
2

Zdaję sobie sprawę, że jest to nieco stary, ale używam Windsor Castle, i to było dość łatwo się profile AutoMapper ładowane za pomocą instalatora:

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)); 
     } 
    } 
} 

Instalator by odebrać MeetingMapperProfile pokazany w pytaniu lub jakiejkolwiek innej klasie opartej na AutoMapper's Profile.