AutoMapper:在映射过程中忽略特定的字典项

5

背景:

有2个主要的类,看起来像这样:

public class Source
{
   public Dictionary<AttributeType, object> Attributes { get; set; }
}

public class Target
{
   public string Title { get; set; }
   public string Description { get; set; }
   public List<Attribute> Attributes { get; set; }
}

还有子类型/集合/枚举类型:

public class Attribute
{
   public string Name { get; set; }
   public string Value { get; set; }
}

public enum AttributeType
{
    Title,
    Description,
    SomethingElse,
    Foobar
}

目前我的地图长这样:

 CreateMap<Source, Target>()
  .ForMember(dest => dest.Description, opt => opt.MapAttribute(AttributeType.Description))
  .ForMember(dest => dest.Title, opt => opt.MapAttribute(AttributeType.Title));

MapAttribute 方法通过从 Dictionary 中获取项,并使用我提供的 AttributeType,将其作为 (名称&值) 对象添加到目标集合中(如果键不存在,则使用 try get 返回一个空对象)...

经过所有这些操作,我的目标集合最终变成了这样:

{ 
  title: "Foo", 
  attributes: [
     { name: "SomethingElse", value: "Bar" }, 
     { name: "Title", value: "Foo"}
  ] 
}


问题:

我该如何将其余项目映射到目标类,但需要排除特定的键(例如,标题或描述)。例如,在Target.Attributes集合中排除了具有目标中已定义位置的Source.Attribute项目,“剩余”属性仍然进入Target.Attributes。

为了更加清晰(如果我的源代码是这样的):

{ attributes: { title: "Foo", somethingelse: "Bar" } }

这将被映射到这样一个目标:

{ title: "Foo", attributes: [{ name: "SomethingElse", value: "Bar" }] }

我尝试过这个方法,但它无法编译,提示如下:

仅支持在类型的顶级单独成员上为成员提供自定义配置。

CreateMap<KeyValuePair<AttributeType, object>, Attribute>()
   .ForSourceMember(x => x.Key == AttributeType.CompanyName, y => y.Ignore())
1个回答

3

在映射配置中,可以预处理值,使得某些值甚至不会传递到目标。我正在使用 AutoMapper v6.1.1,虽然有些差异,但是思路应该是相同的。

为了使事情正常工作,我必须先将 KeyValuePair<AttributeType, object> 添加到 Attribute 映射中(MapAttribute 只返回字典值)。

CreateMap<KeyValuePair<AttributeType, object>, Attribute>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(s => s.Key))
    .ForMember(dest => dest.Value, opt => opt.MapFrom(s => s.Value));

由于已经定义了应该被忽略的属性,因此它们将进入忽略列表,基于此映射将过滤掉多余的属性。

var ignoreAttributes = new[] {AttributeType.Description, AttributeType.Title};
CreateMap<Source, Target>()
    .ForMember(dest => dest.Description, opt => opt.MapFrom(s => s.MapAttribute(AttributeType.Description)))
    .ForMember(dest => dest.Title, opt => opt.MapFrom(s => s.MapAttribute(AttributeType.Title)))
    .ForMember(dest=>dest.Attributes, opt=> opt.MapFrom(s=>s.Attributes
        .Where(x=> !ignoreAttributes.Contains(x.Key))));

根据最终的映射示例

var result = Mapper.Map<Target>(new Source
{
    Attributes = new Dictionary<AttributeType, object>
    {
        {AttributeType.Description, "Description"},
        {AttributeType.Title, "Title"},
        {AttributeType.SomethingElse, "Other"},
    }
});

结果将填充标题、描述和仅一个属性SomethingElse。

在此输入图片描述 在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接