使用Automapper静态初始化API在何处放置映射

时间:2018-01-29 15:12:08

标签: c# asp.net automapper

我正在使用Automapper 6.2.2,我试图在Web应用程序中进行设置。我试图使用直接放在我的Global.asax文件中的静态Automapper.Initialize()方法。

public class WebApiApplication : HttpApplication
{
    protected void Application_Start()
    {

        AutoMapper.Mapper.Initialize(cfg =>
        {
            cfg.AllowNullCollections = true;

            cfg.CreateMap<LoadArea, LoadAreaWithoutPlannedSlotDto>();
            cfg.CreateMap<LoadArea, LoadAreaDto>();
            cfg.CreateMap<LoadAreaForCreationDto, LoadArea>().Ignore(d => d.Slots);
            cfg.CreateMap<LoadArea, LoadAreaForUpdateDto>();
            cfg.CreateMap<LoadAreaForUpdateDto, LoadArea>().ForMember(m => m.Code, i => i.UseDestinationValue());

            cfg.CreateMap<PlannedSlot, PlannedSlotDto>();
            cfg.CreateMap<PlannedSlotForCreationDto, PlannedSlot>().Ignore(d => d.Area);
            cfg.CreateMap<PlannedSlotForUpdateDto, PlannedSlot>();
            cfg.CreateMap<UserToReturnDto, User>();
            cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>();

        });

        AreaRegistration.RegisterAllAreas();
        UnityConfig.RegisterComponents();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

    }
}

奇怪的问题是,虽然此代码在启动时运行,但是映射已创建,但实际上并未配置它们。

因此,如果我尝试忽略Mapper.Initialize(...)方法中的属性,它就不起作用,并且在映射发生时遇到未映射的属性时会出现错误。

我尝试使用:

cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>().ForMember(d => d.LoadArea, opt => opt.Ignore());

也尝试过:

cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>(MemberList.None);

以及其他一些组合,包括一个忽略所有未映射成员的扩展方法:

        public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
    {
        map.ForMember(selector, config => config.Ignore());
        return map;
    }

但是如果我尝试忽略我的控制器中的Inline属性,那么它的工作原理如下:

[HttpPost]
    [Route("{loadAreaId}/details")]
    public IHttpActionResult AddLoadAreaSlotDetails([FromUri] string loadAreaId, [FromBody] LoadAreaSlotDetailForAddDto loadAreaSlotDetails)
    {

        var loadAreaSlotDetailEntity = Mapper.Map<LoadAreaSlotDetailForAddDto, LoadAreaSlotDetail>(loadAreaSlotDetails, opt => opt.ConfigureMap().ForMember(d => d.LoadArea, o => o.Ignore()));
        _repo.AddLoadAreaSlotDetail(loadAreaSlotDetailEntity);

        return Ok();
    }

这向我证明Ignore有效但同时我假设我错误地初始化和配置我的映射但我不知道为什么因为许多其他示例正在以相同的方式初始化静态API。我在.NET Core项目(在ConfigureServices方法中)执行相同操作并且映射工作,它默认也忽略未映射的属性。

为什么会这样?

1 个答案:

答案 0 :(得分:2)

您是否尝试过使用AutoMapper配置文件?

AutoMapper Configuration

然后我可以在我的WebApi应用程序的Startup.cs中配置它。我使用SimpleInjector作为我的容器:

var profiles =
    Assembly
         .GetExecutingAssembly()
         .GetTypes()
         .Where(t => typeof(Profile).IsAssignableFrom(t))
         .ToList();

Mapper.Initialize(
    mp =>
        {
            var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfiles(profiles));

            var mapper = mapperConfiguration.CreateMapper();

            container.Register(() => mapper, Lifestyle.Scoped);
        });

然后,您需要定义一个或多个配置文件,具体取决于您希望如何拆分自动映射器配置。

public class UserProfile : Profile
{
    public UserProfile()
    {
        CreateMap<UserDetails, UserTransferObject>();
        CreateMap<UserAndAccountDetails, UserAndAccountTransferObject>();
        CreateMap<User, UserAndAccountTransferObject>()
            .ForMember(
                dest => dest.DifferentPropertyName,
                orig => orig.MapFrom(src => src.OriginalPropertyName));     
    }
}