C# AutoMapper 属性映射与 Profile 和 AutoMap SourceMember 装饰器不尊重条件

问题描述 投票:0回答:1

经过大量阅读和尝试/错误后,我决定在这里发帖以吸引更多受众的意见。这是一个简单的用例,DTO 映射到实体类。 DTO 的属性名称非常奇怪,因为它是从 Salesforce PubSub CDC API 的 Avro 消息正文解码的,并且 Salesforce 有一种微妙的方式为自定义字段添加后缀。

因此,我使用 [SourceMember] 属性来装饰目标成员属性,因此 AutoMapper 将知道如何为相应装饰的目标获取值。除此之外,我还使用 AutoMapper Profile 类为所有映射中的所有成员设置一个条件,以忽略空源字段。这是因为 DTO 的大多数成员属性在大多数情况下可能为 null,因为这是 CDC 事件。

这就是问题 - 使用配置文件(指定地图的条件)并在目标类上使用 [AutoMap] 类属性来支持 [SourceMember] 装饰器时,似乎存在某种配置/设置冲突。查看此处的 AutoMapper 文档 https://docs.automapper.org/en/stable/Attribute-mapping.html 它说“属性映射可以补充或替换流畅的映射配置”。我只能假设正在发生“替换”操作,而不是“补充”。

这里最奇怪的是第二个问题——如果我注释掉

c.AddProfile(new AutoMapperProfile())
那么 AutoMapper 将尊重 [SourceMember] 装饰器,但不尊重配置文件中的忽略 null 条件。

但是如果我注释掉

c.AddMaps(typeof(TargetClass))
AutoMapper 将尊重配置文件中的忽略 null 条件,但它不会尊重 [SourceMember] 装饰器。

最终结果是我可以在从 SourceDtoClass 映射的 TargetEntityClass 上获得良好的属性值(使用 [SourceMember] 装饰器),-或者-我最终用 SourceDtoClass 中的空值覆盖 TargetEntityClass 上的值,这是我想避免的(例如通过使用条件)

下面是源 DTO、目标类和 AutoMapper 配置的示例。

环境为.NET 7、EF Core 7.0.9、AutoMapper 和 AutoMapper 扩展 12.0.1、Visual Studio for Mac v17.6.1。

配置:

var autoMapperConfig = new MapperConfiguration(c =>
  {
   c.AddProfile(new AutoMapperProfile());
   c.AddMaps(typeof(TargetClass));
  });

IMapper mapper = autoMapperConfig.CreateMapper();
services.AddSingleton(mapper);

简介:

public class AutoMapperProfile : Profile {
  public AutoMapperProfile() {
            CreateMap<SourceDtoClass, TargetEntityClass>()
                .ForAllMembers(option => option.Condition((src, dst, srcMember) => srcMember != null));
  }
}

源D到类:

public class SourceDtoClass {
  public string? Name { get; set; } = "";
  public string? Phone_number_1__c { get; set; } = "";
}

目标实体类:

[DataContract]
[Serializable]
[AutoMap(typeof(SourceDtoClass))]
public class TargetEntityClass {

  public string Name { get; set; } = "";
  [DataMember]
  [SourceMember("Phone_number_1__c")]
  public string? Phone { get; set; } = "";

}

用途:
(假设映射器已通过 IoC 给出,sourceDtoClass 已实例化,targetEntityClass 是一个完全水合的 EF 实体类实例,其值来自 EF SQL Select 交互)

mapper.map(sourceDtoClass,targetEntityClass)
c# entity-framework-core automapper
1个回答
0
投票

感谢@LucianBargaoanu 的评论,在 AutoMapper InternalAPI 中使用 ForAllPropertyMaps 有效!

虽然我不确定为什么当目标上的 int 数据类型为目标时(当目标已经存在值时,例如覆盖),源类中字符串数据类型上的忽略空源值会产生零赋值发生)我找到了一个解决方法,只是不在该属性上提供 [SourceMember] 装饰就排除了它。我发现我毕竟不需要映射该属性,但我仍然希望我更多地了解 AutoMapper 在这方面的行为。

配置方案如下:

var autoMapperConfig = new MapperConfiguration(config =>
   {
     config.AddMaps(typeof(TargetEntityClass));
     InternalApi.Internal(config).ForAllPropertyMaps(
         propertymaps => true, (propertymap, condition) =>
            {
             condition.Condition((source, destination, srcval) => srcval !=null);
             });
   });
© www.soinside.com 2019 - 2024. All rights reserved.