Autofac和Automapper新API - ConfigurationStore已不复存在

时间:2016-02-03 20:53:25

标签: .net automapper autofac

我已经在.Net应用中使用Automapper和Autofac一段时间了。我用这种方式配置它们:

builder.RegisterAssemblyTypes(typeof (OneOfMyMappingProfiles).Assembly)
        .Where(t => t.IsSubclassOf(typeof (Profile)))
        .As<Profile>();

builder.Register(ctx => new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers))
        .AsImplementedInterfaces()
        .SingleInstance()
        .OnActivating(x =>
        {
            foreach (var profile in x.Context.Resolve<IEnumerable<Profile>>())
            {
                x.Instance.AddProfile(profile);
            }
        });

builder.RegisterType<MappingEngine>()
            .As<IMappingEngine>().SingleInstance();

使用最新版本的Automapper(4.2),API已发生变化,我无法转换为新的API。 ConfigurationStore似乎不再存在。根据文件,注册IOC的方式现在是这样的:

 var profiles =
        from t in typeof (AutoMapperRegistry).Assembly.GetTypes()
        where typeof (Profile).IsAssignableFrom(t)
        select (Profile)Activator.CreateInstance(t);

    var config = new MapperConfiguration(cfg =>
    {
        foreach (var profile in profiles)
        {
            cfg.AddProfile(profile);
        }
    });

    For<MapperConfiguration>().Use(config);
    For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));

但是正在使用StructureMap。上半部分没有问题,但我不知道如何翻译“For&lt;&gt; .Use()”部分。我如何在Autofac中做到这一点?

4 个答案:

答案 0 :(得分:18)

行。解决了这个问题。这是替代品:

var profiles =
        from t in typeof(LocationMappingProfile).Assembly.GetTypes()
        where typeof(Profile).IsAssignableFrom(t)
        select (Profile)Activator.CreateInstance(t);

        builder.Register(ctx => new MapperConfiguration(cfg =>
        {
            foreach (var profile in profiles)
            {
                cfg.AddProfile(profile);
            }
        }));

        builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>();

<强>更新

以下是个人资料的示例。超级简单。在这种情况下,我只有一个映射。但我可以添加其他人。我尝试通过实体将它们逻辑地保持在一起。因此,在这种情况下,从ProviderDetail到ProviderDetail的任何未来映射都将在此文件中。映射到不同的实体将位于单独的mappingprofile类中。配置文件类中没有注入任何内容:

 public class ProviderMappingProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<ProviderDetail, ProviderListItem>();
    }
}

<强> UPDATE2

以下是一个证明映射正确的测试示例:

public class ProviderMappingProfileTests
{
    [Fact]
    public void CreateMap_ProviderDetailToProviderQueryResult_IsValid()
    {
        var config = new MapperConfiguration(cfg =>
            cfg.CreateMap<ProviderDetail, ProviderListItem>()
            );

        config.AssertConfigurationIsValid();
    }
}

答案 1 :(得分:4)

通过Autofac注册Automapper的另一种有趣方法,即动态注册程序集中的所有自定义配置文件。

在这里,您可以为所需的所有装配注册配置文件。

builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Program)))
    .Where(t => t.BaseType == typeof(Profile)
                && !t.IsAbstract && t.IsPublic)
    .As<Profile>();

在这里解决这些问题:

builder.Register(ctx => new MapperConfiguration(cfg =>
{
    foreach (var profile in ctx.Resolve<IEnumerable<Profile>>())
        cfg.AddProfile(profile);
}));

builder.Register(ctx => ctx.Resolve<MapperConfiguration>()
                           .CreateMapper())
       .As<IMapper>()
       .SingleInstance();

另外,可以使用

.CreateMapper(ctx.Resolve)

而不是

.CreateMapper()

解决配置文件中的内部依赖关系。但它需要删除

.SingleInstance()

来自注册。

以下是BTW的用法:

public SomeAutowiredClass
{
        public IMapper Mapper { get; set; }

        public void SomeMethod(SomeModel model){
             Mapper.Map<AnotherModel>(model)
        }
}

答案 2 :(得分:2)

我同意上述解决方案。我们不能在下面使用反射吗?

public static IMapper RegisterAutoMapper()
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<ApiMappingProfile1>();
        cfg.AddProfile<ApiMappingProfile2>();
        // Add all your profiles
    });
    var mapper = config.CreateMapper();
    return mapper;
}

在Autofac注册

builder.Register(c => AutoMapperConfig.RegisterAutoMapper()).As<IMapper>()
    .InstancePerLifetimeScope().PropertiesAutowired().PreserveExistingDefaults();

答案 3 :(得分:0)

这是一个小修改,对我有用。它会扫描所有已加载的程序集并从中加载所有AutoMapper配置文件。

<script>
    var played = moment.duration('{{ $ArenaLastGameTimePlayed }}'); //PT8M10.9525157S
    //console.log(played);
    $("#time").append( "<b>" + played.humanize() + "</b>");
</script>

它需要过滤抽象和私有类以跳过内置的AutoMapper。