15

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

我的问题是如何配置 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

4 回答 4

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

此代码在您的引导程序中运行一次,之后任何类型的依赖项都将使用您的 custom 配置IMappingEngine的静态属性的值提供服务。Mapper.EngineAutoMapperProfile

于 2012-09-26T15:34:13.043 回答
7

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

在新版本(4.2.0 >=)中,我们应该持有并通过 DI 传递IMapper

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

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

于 2016-02-16T11:16:39.883 回答
1

这是我最终得到的结果,因为我不知道如何在 Mapper.Engine 上设置配置并将其传递给 For().Use。

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>();
}
于 2012-09-26T18:10:55.377 回答
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

于 2014-02-06T23:11:53.567 回答