Can AutoMapper indirectly smooth this mapping?

I am trying to display between two lists of objects. The source type has a complex property of type A ; destination type is a flattened subset of type A plus an additional scalar property that is in the source type.

 public class A { public int Id { get; set; } public string Name { get; set; } } public class Source { public A MyA { get; set; } public int SomeOtherValue { get; set; } } public class Destination { public string Name { get; set; } public int SomeOtherValue { get; set; } } 

If this is not clear, I would like Source.MyA.Name display on Destination.Name and Source.SomeOtherValue to display on Destination.SomeOtherValue .

In fact, type A has a dozen or so properties, about which 80% go to properties with the same name in Destination . I can get the job to work if I explicitly describe the mappings in CreateMap as follows:

 CreateMap<Source, Destination>() .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.MyA.Name)); 

The disadvantage here is that I do not want to add a ForMember line for each of the properties of A that need to be copied to Destination . I was hoping I could do something like:

 CreateMap<Source, Destination>() .ForMember(dest => dest, opt => opt.MapFrom(src => src.MyA)); 

But if I try above, I get a runtime error when registering the mapping: "User configuration for members is supported only for individual top-level members for a type."

thanks

+4
source share
3 answers

create mappings between A and Destination and Source and Destination , and then use AfterMap() to use the first display in the second

 Mapper.CreateMap<A, Destination>(); Mapper.CreateMap<Source, Destination>() .AfterMap((s, d) => Mapper.Map<A, Destination>(s.MyA, d)); 

then use it as follows:

 var res = Mapper.Map<Source, Destination>(new Source { SomeOtherValue = 7, MyA = new A { Id = 1, Name = "SomeName" } }); 
+5
source

As a workaround, you can use a custom type converter with an additional property in the destination type to avoid recursion.

 [TestFixture] public class MapComplexType { [Test] public void Map() { Mapper.CreateMap<A, Destination>(); Mapper.CreateMap<Source, Destination>().ConvertUsing(new TypeConvertor()); var source = new Source { MyA = new A { Name = "Name" }, SomeOtherValue = 5 }; var dest = new Destination(); Mapper.Map(source, dest); Assert.AreEqual(dest.Name, "Name"); } } public class TypeConvertor : ITypeConverter<Source, Destination> { public Destination Convert(ResolutionContext context) { var destination = (Destination) context.DestinationValue; if (!((Destination)context.DestinationValue).IsMapped || destination == null) { destination = destination ?? new Destination(); destination.IsMapped = true; // To avoid recursion Mapper.Map((Source)context.SourceValue, destination); destination.IsMapped = false; // If you want to map the same object few times } Mapper.Map(((Source)context.SourceValue).MyA, destination); return (Destination)context.DestinationValue; } } public class A { public int Id { get; set; } public string Name { get; set; } } public class Source { public A MyA { get; set; } public int SomeOtherValue { get; set; } } public class Destination { public string Name { get; set; } public int SomeOtherValue { get; set; } // Used only for mapping purposes internal bool IsMapped { get; set; } } 
0
source

Try it,

 Mapper.CreateMap<A, Destination>(); Mapper.CreateMap<Source, Destination>() .ForMember(destination => destination.Name, options => options.MapFrom(source => Mapper.Map<A, Destination>(source.MyA).Name)); var objSource = new Source { SomeOtherValue = 7, MyA = new A { Id = 1, Name = "SomeName" } }; var result = Mapper.Map<Source, Destination>(objSource); 
0
source

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


All Articles