AutoMapper AutoMapperMappingException

时间:2016-08-16 08:18:46

标签: c# .net asp.net-mvc mapping automapper

我发现了AutoMapper的一些非常奇怪的行为。 这个简单的代码

internal class Program
{
    private static void Main(string[] args)
    {
        Mapper.Initialize(cfg => { cfg.CreateMap<MyClass1, MyClass2>(); });
        Mapper.Initialize(cfg => { cfg.CreateMap<MyClass3, MyClass4>(); });

        var dto = new MyClass1();
        Mapper.Map<MyClass1, MyClass2>(dto);
    }
}

public class MyClass1
{
}

public class MyClass2
{
}

public class MyClass3
{
}

public class MyClass4
{
}

生成异常:

  

缺少类型映射配置或不支持的映射。

     

映射类型:MyClass1 - &gt; MyClass2 ConsoleApplication2.MyClass1 - &gt;   ConsoleApplication2.MyClass2

但是如果改变两个初始化行的顺序,就像这样

Mapper.Initialize(cfg => { cfg.CreateMap<MyClass3, MyClass4>(); });
Mapper.Initialize(cfg => { cfg.CreateMap<MyClass1, MyClass2>(); });
一切都很好。怎么了?发生了什么事?

1 个答案:

答案 0 :(得分:2)

长话短说,Jimmy 暂时远离AutoMapper中的静态内容,转而使用基于实例的映射。然而,正如吉米评论的那样:

  

静态映射器不会被删除,只能在代码中的任何地方调用CreateMap

质疑错误的答案是你试图初始化两次,而不是一次。

要回答有关如何在代码中分散不同配置的下一个问题,请使用Profile

要回答如何配置所有内容,请参阅以下内容:

对于AutoMapper 5.1.1

有一个MapperConfigurationExpression

https://github.com/AutoMapper/AutoMapper/blob/master/src/AutoMapper/Configuration/MapperConfigurationExpression.cs

您可以传递给映射器,或Mapper获取Action<IMapperConfigurationExpression>

IMapperConfigurationExpression暴露了这个:

void AddProfile(Profile profile)

所以你几乎可以像下面这样做,但是在IMapper接口上注册所有内容,这就像4.2.1正朝着这样做。

对于AutoMapper 4.2.1(配置文件简介)

以下是一个示例配置文件:

using AutoMapper;

using TreasuryRecords.Database.Models;
using TreasuryRecords.Requests.Account.Models;

public class AccountMappings : Profile
{
    protected override void Configure()
    {
        this.CreateMap<RegisterDto, Client>()
            .ForMember(x => x.UserName, c => c.MapFrom(x => x.Email));
    }
}

以下是我如何注册个人资料的示例:

using System;
using System.Linq;
using System.Reflection;

using AutoMapper;

using TreasuryRecords.Requests.Authenticate.Login;

public static class AutoMapperConfig
{
    public static void Configure()
    {
        Assembly
            .GetExecutingAssembly()
            .RegisterConfigurations();

        typeof(LoginRequest)
            .Assembly
            .RegisterConfigurations();
    }

    public static void RegisterConfigurations(this Assembly assembly)
    {
        var types = assembly.GetTypes();

        var automapperProfiles = types
                                    .Where(x => typeof(Profile).IsAssignableFrom(x))
                                    .Select(Activator.CreateInstance)
                                    .OfType<Profile>()
                                    .ToList();

        // so here you can pass in the instance of mapper
        // I just use the static for ease
        automapperProfiles.ForEach(Mapper.Configuration.AddProfile);
    }
}

这是我将它添加到DI的方式:

public static void RegisterAutoMapper(this IUnityContainer container)
{
    container.RegisterType<IMapper>(new InjectionFactory(_ => Mapper.Instance));
}

我在这里使用了unity,但这非常简单,只需在接口Mapper.Instance上注册IMapper

然后我注入IMapper并像这样使用它:

this.mapper.Map<Client>(message.RegistrationDetails);