AutoMapper: ignore specific dictionary positions (s) during matching

Context:

There are 2 main classes that look something like this:

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; } } 

And sub / collection / Enum type:

 public class Attribute { public string Name { get; set; } public string Value { get; set; } } public enum AttributeType { Title, Description, SomethingElse, Foobar } 

Currently, my map is as follows:

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

Where MapAttribute gets the element from the Dictionary and uses the AttributeType that I provided, adds it to the target collection as an object (name and value) (using try get and returning empty if the key does not exist) ...

After that, all my targets look like this:

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


Question:

How can I move on to displaying the remaining elements in the target class, but I need to be able to exclude certain keys (for example, name or description). EG. Source.Attribute elements that have a specific place in the target are excluded from the Target.Attributes collection, and the "left-over" properties still apply to Target.Attributes.

For clarity (if my source looks like this):

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

it will be matched with this type:

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

I tried to do this, but it does not compile, stating the following:

Custom configuration for members is only supported for individual top-level members for a type.

 CreateMap<KeyValuePair<AttributeType, object>, Attribute>() .ForSourceMember(x => x.Key == AttributeType.CompanyName, y => y.Ignore()) 
+5
source share
1 answer

You can pre-filter the values โ€‹โ€‹in the display configuration so that some values โ€‹โ€‹do not even fall into the target. I use automapper v6.1.1 , there is a difference, but the idea should be the same)

To do everything I need, I must first add a KeyValuePair<AttributeType, object> mapping to Attribute ( MapAttribute just returns the dictionary value)

 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)); 

As he determined which attributes should be ignored, they will go to the ignore list, on the basis of which redundant attributes will be filtered

 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)))); 

Based on the latest display example

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

the result will fill in Titel, Description and only one attribute SomethingElse

enter image description here enter image description here

+3
source

Source: https://habr.com/ru/post/1271858/


All Articles