使用AutoMapper将嵌套元素映射到相关列表 [英] Map nested elements to related lists using AutoMapper

查看:49
本文介绍了使用AutoMapper将嵌套元素映射到相关列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两组对象

我在C#客户端应用程序中使用的对象:

Objects that I use in C# client application:

public class EmployeeClient
{
    public int Id { get; set; }

    public int DepartmentId { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string MiddleName { get; set; }
}

public class DepartmentClient
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class OrganizationClient
{
    public int Id { get; set; }

    public string Name { get; set; }

    public List<DepartmentClient> Departments { get; set; }

    public List<EmployeeClient> Employees { get; set; }
}

和DTO:

public class EmployeeDto
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string MiddleName { get; set; }
}

public class DepartmentDto
{
    public int Id { get; set; }

    public string Name { get; set; }

    public List<EmployeeDto> Employees { get; set; }
}

public class OrganizationDto
{
    public int Id { get; set; }

    public string Name { get; set; }

    public List<DepartmentDto> Departments { get; set; }
}

我使用AutoMapper,并且需要配置映射客户端-> DTO和DTO->客户端. 我像这样实现了映射DTO-> Client:

I use AutoMapper and I need to configure mapping Client -> DTOs and DTOs -> Client. I implemented mapping DTOs->Client like this:

public class DtoToClientMappingProfile: Profile
{
    public DtoToClientMappingProfile()
    {
        CreateMap<EmployeeDto, EmployeeClient>();

        CreateMap<DepartmentDto, DepartmentClient>();

        CreateMap<OrganizationDto, OrganizationClient>()
            .ForMember(dest => dest.Employees, opt => opt.ResolveUsing(src => src.Departments.SelectMany(d => d.Employees)))
            .AfterMap(AfterMap);
    }

    private void AfterMap(OrganizationDto dto, OrganizationClient client)
    {
        foreach (var department in dto.Departments)
        {
            foreach (var employee in department.Employees)
            {
                var clientEmployee = client.Employees.First(e => e.Id == employee.Id);
                clientEmployee.DepartmentId = department.Id;
            }
        }
    }
}

这不是通用解决方案,但对我有用.

It is not universal solution, but is works for me.

我只找到了一种实现Client-> DTO映射的方法:

I've found only one option how mapping Client->DTOs could be implemented:

public class ClientToDtosMappingProfile : Profile
{
    public ClientToDtosMappingProfile()
    {
        CreateMap<EmployeeClient, EmployeeDto>();

        CreateMap<DepartmentClient, DepartmentDto>();

        CreateMap<OrganizationClient, OrganizationDto>()
            .AfterMap(AfterMap);
    }

    private void AfterMap(OrganizationClient client, OrganizationDto dto)
    {
        foreach (var employee in client.Employees)
        {
            var departmentDto = dto.Departments.First(d => d.Id == employee.DepartmentId);
            if (departmentDto.Employees == null)
            {
                departmentDto.Employees = new List<EmployeeDto>();
            }

            var configuration = (IConfigurationProvider)new MapperConfiguration(cfg =>
            {
                cfg.AddProfiles(typeof(ClientToDtosMappingProfile));
            });

            var mapper = (IMapper)new Mapper(configuration);

            var employeeDto = mapper.Map<EmployeeDto>(employee);
            departmentDto.Employees.Add(employeeDto);
        }
    }
}

它可以工作,但是我不喜欢这种解决方案,因为每次映射对象时都应该创建新的Mapper实例.在我的真实代码中,Employee有很多嵌套元素,并且映射是在多个配置文件中配置的.

It works, but I do not like this solution because I should create instance of new Mapper every time I map objects. In my real code Employee has a lot of nested elements and mapping is configured in multiple profiles.

有什么想法可以更好地实施它?

Any ideas how it could be implemented better?

推荐答案

我使用ResolutionContext使我的代码更好了.不允许在AfterMap函数中创建映射器.

I made my code a bit better using ResolutionContext. It allows not to create mappers in AfterMap function.

DtoToClientMappingProfile:

DtoToClientMappingProfile:

public class DtoToClientMappingProfile: Profile
{
    public DtoToClientMappingProfile()
    {
        CreateMap<EmployeeDto, EmployeeClient>();

        CreateMap<DepartmentDto, DepartmentClient>();

        CreateMap<OrganizationDto, OrganizationClient>()
            .ForMember(dest => dest.Employees, opt => opt.Ignore())
            .AfterMap(AfterMap);
    }

    private void AfterMap(OrganizationDto dto, OrganizationClient client, ResolutionContext resolutionContext)
    {
        if (dto.Departments == null)
        {
            return;
        }

        client.Departments = new List<DepartmentClient>();
        foreach (var department in dto.Departments)
        {
            var departmentClient = resolutionContext.Mapper.Map<DepartmentClient>(department);
            client.Departments.Add(departmentClient);
            if (department.Employees == null)
            {
                continue;
            }

            if (client.Employees == null)
            {
                client.Employees = new List<EmployeeClient>();
            }

            foreach (var employee in department.Employees)
            {
                var employeeClient = resolutionContext.Mapper.Map<EmployeeClient>(employee);
                employeeClient.DepartmentId = department.Id;
                client.Employees.Add(employeeClient);
            }
        }
    }

ClientToDtosMappingProfile:

ClientToDtosMappingProfile:

public class ClientToDtosMappingProfile : Profile
{
    public ClientToDtosMappingProfile()
    {
        CreateMap<EmployeeClient, EmployeeDto>();

        CreateMap<DepartmentClient, DepartmentDto>();

        CreateMap<OrganizationClient, OrganizationDto>()
            .AfterMap(AfterMap);
    }

    private void AfterMap(OrganizationClient client, OrganizationDto dto, ResolutionContext resolutionContext)
    {
        if (client.Employees == null)
        {
            return;
        }

        foreach (var employee in client.Employees)
        {
            var departmentDto = dto.Departments.First(d => d.Id == employee.DepartmentId);
            if (departmentDto.Employees == null)
            {
                departmentDto.Employees = new List<EmployeeDto>();
            }

            var employeeDto = resolutionContext.Mapper.Map<EmployeeDto>(employee);
            departmentDto.Employees.Add(employeeDto);
        }
    }
}

这篇关于使用AutoMapper将嵌套元素映射到相关列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆