【问题标题】:Inject AutoMapper注入 AutoMapper
【发布时间】:2009-11-12 03:37:20
【问题描述】:

我一直致力于将 AutoMapper 注入控制器。我喜欢 Code Camp Server 的实现。它围绕 AutoMapper 的 IMappingEngine 创建一个包装器。依赖注入是使用 StructureMap 完成的。但我的项目需要使用 Castle Windsor。那么,我们如何使用 Windsor 实现以下依赖注入和设置呢?我不是在 Castle Windsor 中寻找逐行等效实现。如果您想这样做,请随意。相反,什么是 Windsor 等效于 StructureMap 的注册表和配置文件?我需要 Profile 来定义 CreateMap,如下所示。

谢谢。

会议负责人

public MeetingController(IMeetingMapper meetingMapper, ...)

会议映射器

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

    ......
}

自动映射注册表

public class AutoMapperRegistry : Registry
{

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

会议映射器简介:

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

【问题讨论】:

    标签: castle-windsor structuremap automapper


    【解决方案1】:

    你的意思是如何在温莎注册?

    你可能需要注册 FactorySupportFacility 拳头...我目前无法检查。

    container.AddFacility<FactorySupportFacility>();
    

    然后

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

    【讨论】:

    • StructureMap 中的 Profile 部分呢? Mapper.CreateMap.ForMember() 从 MeetingMapperProfile 类中调用。如何在温莎城堡做到这一点?谢谢。
    • 这个配置文件是什么?它有什么作用?如果您只是指 Configure 方法,那么您可以在其中将组件注册到容器中,它对容器没有任何依赖关系 AFAICS
    • StructureMap 中的配置文件能够在运行时根据使用它们的上下文切换服务(即类)的不同具体实现。但是,如果您查看会议配置文件,它实际上并没有这样做。必须在 MeetingMapper 调用 _mappingEngine.Map() 之前调用 Meeting Profile 中的 Mapper.CreateMap.ForMember(...)。我正在考虑在温莎创建一个设施来做会议档案现在正在做的事情。你怎么看?谢谢。
    【解决方案2】:

    我不熟悉 Castle Windsor,但这里是 StructureMap 语法。您需要对注册表进行一些不同的设置。无需将 IMappingEngine 设置为 Mapper.Engine,您将不得不配置更多接口。还需要做一些工作,但这将允许您将配置文件设置为注册的一部分。

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

    【讨论】:

      【解决方案3】:

      我意识到这有点旧,但我使用的是 Castle Windsor,而且使用安装程序加载 AutoMapper 配置文件相当容易:

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

      此安装程序将选择问题中显示的MeetingMapperProfile,或基于 AutoMapper 的Profile 的任何其他类。

      【讨论】:

        猜你喜欢
        • 2011-05-11
        • 1970-01-01
        • 1970-01-01
        • 2011-04-06
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-03
        相关资源
        最近更新 更多