如何使用StructureMap注入AutoMapper IMappingEngine

时间:2012-09-26 15:11:52

标签: dependency-injection automapper structuremap

我为Automapper找到的大多数示例都使用静态Mapper对象来管理类型映射。对于我的项目,我需要使用StructureMap注入IMapperEngine作为对象构造的一部分,以便我们可以在单元测试中模拟映射器,因此我们不能使用静态映射器。我还需要支持配置AutoMapper配置文件。

我的问题是我如何配置StructureMap注册表,以便在构建MyService实例时它可以提供IMappingEngine的实例。

这是服务构造函数签名:

public MyService(IMappingEngine mapper, IMyRepository myRepository, ILogger logger)

这是StructureMap注册表

public class MyRegistry : StructureMap.Configuration.DSL.Registry
{
    public MyRegistry()
    {
        For<IMyRepository>().Use<MyRepository>();
        For<ILogger>().Use<Logger>();
        //what to do for IMappingEngine?
    }
}

我要加载的个人资料

public class MyAutoMapperProfile : AutoMapper.Profile
{
    protected override void Configure()
    {
        this.CreateMap<MyModel, MyDTO>();
    }
}

4 个答案:

答案 0 :(得分:14)

Mapper类具有静态属性Mapper.Engine。使用此命令向容器注册引擎:

For<IMappingEngine>().Use(() => Mapper.Engine);

如果您需要在注入引擎之前加载配置文件,我会将配置代码插入上面的代码段。


<强>更新

您的自定义注册表将如下所示

class MyRegistry : Registry
{
  public MyRegistry()
  {
    For<IMyRepository>().Use<MyRepository>();
    For<ILogger>().Use<Logger>();

    Mapper.AddProfile(new AutoMapperProfile());
    For<IMappingEngine>().Use(() => Mapper.Engine);
  }
}

此代码在您的引导程序中运行一次,类型IMappingEngine的任何依赖项随后将使用您使用自定义Mapper.Engine配置的静态属性AutoMapperProfile的值提供。

答案 1 :(得分:7)

  

将在5.0版中删除静态API。使用a   MapperConfiguration实例并根据需要静态存储。使用   CreateMapper用于创建映射器实例。

在新版本(4.2.0&gt; =)中,我们应该通过DI保留并传递 IMapper

一个简单的配置服务应该是这样的(ASP.NET核心)

services.AddSingleton<IMapper>(_ => new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Foo,Bar>();
            })
            .CreateMapper());

和我们的服务层(在构造函数注入的帮助下):

public class CrudService<TDocument> : ICrudService<TDocument>
    {
        private readonly IMapper _internalMapper;
        private readonly IRepository<TDocument> _repository;

        public CrudService(IRepository<TDocument> repository, IMapper mapper)                
        {
            _internalMapper = mapper;
            _repository = repository;
        }

        public virtual ServiceResult<string> Create<TModel>(TModel foo)
        {
            var bar = _internalMapper.Map<TDocument>(foo);

            try
            {
                _repository.Create(bar);
            }
            catch (Exception ex)
            {
                return ServiceResult<string>.Exception(ex);
            }

            return ServiceResult<string>.Okay(entity.Id);
        }
}

consider TDocument as Bar, and TModel as Foo

更新
AutoMapper 4.2.1发布 - 静态回归

  经过一番反馈和灵魂搜索,老老实实地厌倦了   处理问题时,一些静态API在此恢复   发布。您现在(以及将来)可以使用Mapper.Initialize和   Mapper.Map

答案 2 :(得分:1)

这是我最终得到的结果,因为我无法弄清楚如何在Mapper.Engine上设置配置并将其传递给For()。使用。

public MyRegistry()
{
    For<IMyRepository>().Use<MyRepository>();
    For<ILogger>().Use<Logger>();

    //type mapping
    For<ConfigurationStore>()
        .Singleton()
        .Use(ctx =>
        {
            ITypeMapFactory factory = ctx.GetInstance<ITypeMapFactory>();
            ConfigurationStore store 
                = new ConfigurationStore(factory, MapperRegistry.AllMappers());
            IConfiguration cfg = store;
            cfg.AddProfile<MyAutoMapperProfile>();
            store.AssertConfigurationIsValid();
            return store;
        });
    For<IConfigurationProvider>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
    For<IConfiguration>().Use(ctx => ctx.GetInstance<ConfigurationStore>());
    For<IMappingEngine>().Singleton().Use<MappingEngine>();
    For<ITypeMapFactory>().Use<TypeMapFactory>();
}

答案 3 :(得分:1)

我写了一篇博文,其中显示了我的AutoMapper和StructureMap设置。我已经为AutoMapper 3.1.0(也适用于3.1.1)和3.0.0和2.2.1创建了特定的注册表。

http://www.martijnburgers.net/post/2013/12/20/My-AutoMapper-setup-for-StructureMap.aspx