Mapeo complejo de AutoMapper en C#

Mapeo complejo de AutoMapper en C#

Mapeo complejo de AutoMapper en C# con ejemplos

En este artículo, voy a discutir el Mapeo complejo de AutoMapper en C# con algunos ejemplos. Lea nuestro artículo anterior antes de continuar con este artículo donde discutimos los conceptos básicos de Automapper en C# con algunos ejemplos sencillos. Al final de este artículo, comprenderá qué es AutoMapper Complex Mapping y cuándo y cómo usar AutoMapper Complex Mapping en C# con ejemplos.

Qué es ¿Asignación compleja de AutoMapper en C#?

Cuando ambos tipos involucrados en el mapeo contienen propiedades del tipo complejo, entonces en tales escenarios necesitamos usar AutoMapper Complex Mapping en C#. Entendamos el mapeo complejo de AutoMapper con un ejemplo. Vamos a utilizar las siguientes cuatro clases para esta demostración.

Requisito comercial :

Nuestro requisito es mapear el Empleado objetar a EmployeeDTO objeto. Para simplificar esta demostración, aquí creamos ambas clases con los mismos nombres de propiedad. Pero lo que debemos tener en cuenta aquí es que creamos la propiedad de dirección como un tipo complejo. Luego estamos creando un método estático, es decir, InitializeAutomapper donde escribimos el código de mapeo como se muestra en la imagen de abajo.

A continuación se muestra el código completo.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Step1: Create and populate the Employee object
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);
            
            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.address.City + ", State:" + empDTO.address.Stae + ", Country:" + empDTO.address.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {             
                cfg.CreateMap<Employee, EmployeeDTO>();
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }
    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO address { get; set; }
    }
    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
    public class AddressDTO
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
}

Ahora, cuando ejecute la aplicación, obtendrá la siguiente excepción de tiempo de ejecución.

Ahora, si va a la excepción interna y verifica la propiedad del mensaje, entonces muestra claramente que falta la configuración del tipo de asignación para Dirección y DirecciónDTO. Esto se debe a que en la configuración de nuestro mapeador, hemos especificado Mapper para Employee y EmployeeDTO pero no para el tipo Address y AddressDTO.

¿Cómo resolver el problema anterior?

Para resolver el problema anterior, debe configurar la asignación entre la Dirección y la DirecciónDTO, antes de la Asignación de Empleado y EmpleadoDTO. Entonces, cambie el InitializeAutomapper como se muestra a continuación.

Con los cambios anteriores en su lugar, ahora, si ejecuta la aplicación y luego obtendrá el resultado esperado como se muestra en la imagen a continuación.

¿Qué sucede si cambiamos el nombre de la propiedad de tipo complejo involucrada en el mapeador automático?

Entendamos esto con un ejemplo. Cambiemos la dirección de propiedad compleja a addressDTO de la clase EmployeeDTO como se muestra a continuación.

A continuación se muestra el código completo.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.City + ", State:" + empDTO.addressDTO.Stae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>();
                cfg.CreateMap<Employee, EmployeeDTO>();
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }
}

Ahora ejecute la aplicación. Debería darte el siguiente error.

Esto se debe a que el nombre de la propiedad para addressDTO no se encuentra en el Empleado objeto. Entonces obtenemos el error de referencia nula.

¿Cómo resolver el problema anterior?

Para resolver el problema anterior, necesitamos mapear la dirección propiedad a addressDTO propiedad en la configuración del mapeador como se muestra en la siguiente imagen.

Con los cambios anteriores en la configuración del mapeador automático, ahora ejecute la aplicación y le dará el resultado esperado.

¿Qué sucede si los nombres de propiedad de tipo complejo son diferentes?

Entendamos esto con un ejemplo. Modifiquemos los nombres de las propiedades en AddressDTO clase como se muestra a continuación.

A continuación se muestra el ejemplo completo.
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.EmpCity + ", State:" + empDTO.addressDTO.EmpStae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>();
                cfg.CreateMap<Employee, EmployeeDTO>()
                .ForMember(dest => dest.addressDTO, act => act.MapFrom(src => src.address));
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string EmpCity { get; set; }
        public string EmpStae { get; set; }
        public string Country { get; set; }
    }
}

Cuando ejecutes la aplicación, no te dará ningún error, pero no mapeará la Ciudad y Estado propiedad como se muestra en el siguiente resultado.

Esto se debe a que mapeamos la Dirección objeto con AddressDTO objeto, pero no habíamos mapeado la Ciudad y Estado propiedades con EmpCity y EmpState propiedades. Mapeemos las dos propiedades anteriores y veamos qué sucede. Para mapear las dos propiedades anteriores, necesitamos cambiar el InitializeAutomapper clase como se muestra a continuación.

El código completo se proporciona a continuación:
using System;
using AutoMapper;
namespace AutoMapperDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Address empAddres = new Address()
            {
                City = "Mumbai",
                Stae = "Maharashtra",
                Country = "India"
            };

            Employee emp = new Employee
            {
                Name = "James",
                Salary = 20000,
                Department = "IT",
                address = empAddres
            };

            var mapper =InitializeAutomapper();
            var empDTO = mapper.Map<EmployeeDTO>(emp);

            Console.WriteLine("Name:" + empDTO.Name + ", Salary:" + empDTO.Salary + ", Department:" + empDTO.Department);
            Console.WriteLine("City:" + empDTO.addressDTO.EmpCity + ", State:" + empDTO.addressDTO.EmpStae + ", Country:" + empDTO.addressDTO.Country);
            Console.ReadLine();
        }
        
        static Mapper InitializeAutomapper()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<Address, AddressDTO>()
                .ForMember(dest => dest.EmpCity, act => act.MapFrom(src => src.City))
                    .ForMember(dest => dest.EmpStae, act => act.MapFrom(src => src.Stae)); ;
                cfg.CreateMap<Employee, EmployeeDTO>()
                .ForMember(dest => dest.addressDTO, act => act.MapFrom(src => src.address));
            });

            var mapper = new Mapper(config);
            return mapper;
        }
    }

    public class Employee
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public Address address { get; set; }
    }

    public class EmployeeDTO
    {
        public string Name { get; set; }
        public int Salary { get; set; }
        public string Department { get; set; }
        public AddressDTO addressDTO { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string Stae { get; set; }
        public string Country { get; set; }
    }

    public class AddressDTO
    {
        public string EmpCity { get; set; }
        public string EmpStae { get; set; }
        public string Country { get; set; }
    }
}

Con los cambios anteriores en su lugar, ahora ejecute la aplicación y vea el resultado esperado como se muestra en la imagen a continuación.

En el próximo artículo, discutiremos cómo mapear tipos complejos a tipos primitivos usando automapper en C#. En este artículo, intento explicar la asignación compleja de AutoMapper en C# con algunos ejemplos. Espero que este AutoMapper Complex Mapping en C# artículo le ayudará con su necesidad. Me gustaría tener sus comentarios. Publique sus comentarios, preguntas o comentarios sobre este artículo.