简体   繁体   中英

how to map using Automapper

I have requirement to map two objects. The requirement is train reservation details which will have towardsjourney and return journey details.

public class ReservationSource
{
    public string ReservationNumber{get;set;} 
    public TravelS towardsTravelS{get;set;}
    public TravelS returnTravelS{get;set;}
}

This is the class which is in the ReservationSource class which is to capture towards and return journey details.

public class TravelS
{
   public string travelId{get;set;}
   public ICollection<JourneyS> Journeys{get;set;}
}

Above is the reservation source object. This source needs a mapping to the destination object. Destination object is given below.

public class ReservationDestination
{
    public string ReservationNumber{get;set;}
    public TravelD towardsTravelD{get;set;}
    public TravelD returnTravelD{get;set;}

}

public class TravelD
{
    public string travelId{get;set;}
    public ICollection<JourneyD> Journeys{get;set;}
}
public class JourneyD
{
    public string JourneyId{get;set;}
}
public class JourneyS
{
    public string JourneyId{get;set;}
}

This is my destination object. Here i want to map my source to destination. How do i define mapping config and map.

var config = new mappingConfiguration(cfg=>
{
cfg.CreateMap<ReservationSource,ReservationDestination>()
});

Imapper map = config.CreateMapper();

This part of code maps only the reservationNumber to the destination object. Can someone help me to map all objects. That is towardsTravelS to towardsTravelD and returnTravelS to returnTravelD .

.net core version: 3.1

First of all you forgot to mention this but I assume there also is a class TravelS that looks like this:

public class TravelS
{
    public string TravelId { get; set; }
}

There are a few things missing in your configuration. At the moment AutoMapper doesn't know it has to map properties with different names ( TowardsTravelS => TowardsTravelD etc) so we have to define those aswell:

cfg.CreateMap<ReservationSource, ReservationDestination>()
    .ForMember(dest => dest.ReturnTravelD, opt => opt.MapFrom(src => src.ReturnTravelS))
    .ForMember(dest => dest.TowardsTravelD, opt => opt.MapFrom(src => src.TowardsTravelS));

Here we tell AutoMapper that these properties that have different names need to be mapped.

Secondly TravelS and TravelD are different classes so we need to configure them for mapping as well:

cfg.CreateMap<TravelS, TravelD>();

So we now have something like this:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<ReservationSource, ReservationDestination>()
      .ForMember(dest => dest.ReturnTravelD, opt => opt.MapFrom(src => src.ReturnTravelS))
      .ForMember(dest => dest.TowardsTravelD, opt => opt.MapFrom(src => src.TowardsTravelS));
    cfg.CreateMap<TravelS, TravelD>();
});

var mapper = config.CreateMapper();

var source = new ReservationSource
{
    ReservationNumber = "9821",
    ReturnTravelS = new TravelS
    {
      TravelId = "1"
    },
    TowardsTravelS = new TravelS
    {
      TravelId = "2"
    }
};

var destination = mapper.Map<ReservationDestination>(source);

Console.WriteLine(JsonSerializer.Serialize(destination));

Output:

{"ReservationNumber":"9821","TowardsTravelD":{"TravelId":"2"},"ReturnTravelD":{"TravelId":"1"}}

Try it for yourself here: https://dotnetfiddle.net/FfccVR

Add this in your services in startup:

it's reusable and cleaner

 public void ConfigureServices(IServiceCollection services)
{
            services.AddAutoMapper(Assembly.GetExecutingAssembly());
}

add these interface and class in your project

public interface IMapFrom<T>
{
        void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
using AutoMapper;
using System;
using System.Linq;
using System.Reflection;

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
        }

        private void ApplyMappingsFromAssembly(Assembly assembly)
        {
                var types = assembly.GetExportedTypes()
                .Where(t => t.GetInterfaces()
                .Any(i =>i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>)))
                .ToList();

            foreach (var type in types)
            {
                var instance = Activator.CreateInstance(type);

                var methodInfo = type.GetMethod("Mapping")
                    ?? type.GetInterface("IMapFrom`1").GetMethod("Mapping");

                methodInfo?.Invoke(instance, new object[] { this });

            }
        }
    }

and your source model be like this (map ReservationSource to ReservationSource):

 public class ReservationSource : IMapFrom<ReservationSource>
    {

        public string Name { get; set; }

        public string City { get; set; }

        public void Mapping(Profile profile)
        {
            profile.CreateMap<ReservationSource,ReservationDestination>()
                       .ForMember(dest => dest.ReturnTravelD, opt => opt.MapFrom(src => src.ReturnTravelS))
                       .ForMember(dest => dest.TowardsTravelD, opt => opt.MapFrom(src => src.TowardsTravelS));
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM