ThejaSingireddy
ThejaSingireddy

Reputation: 336

Add inner mapper to AutoMapper mapping profile

I'm trying to map an object of type source to destination and it has some inner mappings needed. I've created a custom mapper like this.

public class CustomerMappingProfile : ITypeConverter<Customer, CustomerDTO>
    {
        public CustomerDTO Convert(Customer input, CustomerDTO destination, ResolutionContext context)
        {
            var CustomerDTO = new ObjectMapper<CustomerDTO, Customer>().Apply(input);
            CustomerDTO.NumbOfSeniorYears = input.YearsList != null ? input.YearsList.Count(p => p.Seniority == SeniorityEnum.Senior) : 0;
            CustomerDTO.NumOfYears = input.NumOfYears.Count();
            CustomerDTO.SearchTypeSelection = input.SearchTypeSelection;
            CustomerDTO.UpgradeTypes = input.UpgradeTypes;
            if (input.Rewards.Any())
            {
                foreach (var reward in input.Rewards)
                {
                    var result = Mapper.Map<Customer.Rewards, RewardsDTO>(reward);
                    CustomerDTO.Rewards.Add(result);
                }
            }
            if (input.EliteLevel == -1)
            {
                CustomerDTO.EliteLevel = null;
            }
            else
            {
                CustomerDTO.EliteLevel = input.EliteLevel;
            }
            var softLoggedIn = Helper.Util.PersServicesUtil.GetCharacteristic(input.Characteristics, "SOFT_LOGGED_IN");
            if (softLoggedIn != null)
            {
                if (softLoggedIn.Equals("true"))
                {
                    CustomerDTO.SoftLoginIndicator = true;
                }
                else
                {
                    CustomerDTO.SoftLoginIndicator = false;
                }
            }
            CustomerDTO.SessionId = Customer.SessionId.ToLower();
            return CustomerDTO;
        }


    }

And I created Mapping profile

  public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Rewards, RewardsDTO>();
            CreateMap<Customer, CustomerDTO>().ConvertUsing(new CustomerMappingProfile());;
        }
    }

And Injected the mapping profile into startup.cs

var config = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile(new MappingProfile());
            });

            services.AddSingleton(sp => config.CreateMapper());

But I'm getting exception InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance. at Inner mapping with in the custom mapper at line Mapper.Map<Customer.Rewards, RewardsDTO>(reward);

Any idea on how to add inner mapping?

Upvotes: 1

Views: 5164

Answers (1)

Prolog
Prolog

Reputation: 3374

I belive all your problems can be resolved by writing proper AutoMapper configuration.

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Rewards, RewardsDTO>();
        CreateMap<Customer, CustomerDTO>()
            .ForMember(destination => destination.NumbOfSeniorYears, options =>
                options.MapFrom(source => source.YearsList.Count(p => p.Seniority == SeniorityEnum.Senior)))
            .ForMember(destination => destination.NumOfYears, options =>
                options.MapFrom(source => source.NumOfYears.Count()))
            .ForMember(destination => destination.EliteLevel, options =>
                options.Condition(source => source.EliteLevel != -1))
            .ForMember(destination => destination.SoftLoginIndicator, options =>
                options.MapFrom((source, dest, context) =>
                    Helper.Util.PersServicesUtil
                        .GetCharacteristic(source.Characteristics, "SOFT_LOGGED_IN")
                        ?.Equals("true") ?? false))
            .ForMember(destination => destination.SessionId, options =>
                options.MapFrom(source => source.SessionId.ToLower()));
    }
}

Judging by your code, I think you are mixing things up, for example concept of mapping profiles with the concept of type converters. You also do not have to map explicitly members that would be mapped anyway (SearchTypeSelection or UpgradeTypes).

I strongly suggest taking a trip to AutoMapper documentation site, so you can build for yourself solid knowledge fundamentals. Having that your mapping code will be more efficient and way shorter for you to write.

And one more thing. IMHO your injection logic looks weird. Have you asked yourself do you really need that custom singleton for AutoMapper? Why not just call AddAutoMapper()? See documentation examples on how to work with AutoMapper in ASP.NET Core.

Upvotes: 3

Related Questions