0

我刚刚使用this question中显示的jevelez方法在通用存储库中实现了显式加载子实体及其父实体。

但是现在我正在尝试将子实体及其父实体映射到 DTO,以便我可以将它们发送到我的 UI 层。

这是我的映射器当前的样子:

映射接口:

public interface IMappingService<TEntity, TDto>
    where TEntity : class 
    where TDto : class
{
    TDto EntityToDto(TEntity entity);
    TEntity DtoToEntity(TDto dto);
    IEnumerable<TDto> EntitiesToDtos(IList<TEntity> entities);
    IEnumerable<TEntity> DtosToEntities(IList<TDto> dtos);
}

实现接口的抽象基方法:

public abstract class MapperBase<TEntity, TDto> : IMappingService<TEntity, TDto>
    where TEntity : class 
    where TDto : class
{
    public abstract TDto EntityToDto(TEntity entity);

    public abstract TEntity DtoToEntity(TDto dto);

    public virtual IEnumerable<TDto> EntitiesToDtos(IList<TEntity> entities)
    {
        return entities.Select(EntityToDto);
    }

    public virtual IEnumerable<TEntity> DtosToEntities(IList<TDto> dtos)
    {
        return dtos.Select(DtoToEntity);
    }
}

以下是两个映射器,它们为两个实体实现这些作为示例:

public class ParentEntityMapper : MapperBase<ParentEntity, ParentEntityDto> , IParentEntityMapper
{

    private readonly IChildEntityMapper _childEntityMapper;

    public ParentEntityMapper(IChildEntityMapper  childEntityMapper)
    {
        _childEntityMapper = childEntityMapper;
    }

    public override ParentEntityDto EntityToDto(ParentEntity entity)
    {
        var dto = new ParentEntityDto();
        dto.Id = entity.Id;
        dto.Title = entity.Title;
        dto.Description = entity.Description;

        if (entity.ChildEntities != null)
        {
            dto.ChildEntities= _childEntityMapper.EntitiesToDtos(entity.ChildEntities .ToList()).ToList();
        }

        return dto;
    }

    public override ParentEntity DtoToEntity(ParentEntityDto dto)
    {
        // This is just a reverse of the above function
    }
}

和子实体映射器:

    public class ChildEntityMapper : MapperBase<ChildEntity, ChildEntityDto>, IChildEntityMapper
    {
        private readonly ParentEntityMapper _parentEntityMapper;

        public ChildEntityMapper(IParentEntityMapper parentEntityMapper)
        {
            _parentEntityMapper = parentEntityMapper;
        }
        public override ChildEntityDto EntityToDto(ChildEntity entity)
        {
            var dto = new ChildEntityDto();

            dto.Id = entity.Id;
            dto.Description = entity.Description;

            if (entity.ParentEntity != null)
            {
                dto.ParentEntity = _parentEntityMapper.EntityToDto(entity.Image);
            }

            return dto;
        }

        public override Anchor DtoToEntity(AnchorDto dto)
        {
            // Just a reverse of the above function
        }
    }

所以我相信你们都可以看到循环依赖发生在哪里。在过去的两天里,我一直在为此苦恼,但我对此仍然很业余,到目前为止,我还无法使用谷歌解决这个问题。

我不想在这部分使用 AutoMapper 和 ValueInjector 之类的工具,因为我在数据库和 DTO 之间进行映射,并且我已经在使用它在 DTO 和 UI 层中的 ViewModel 之间进行映射。

如果可能的话,我希望能够以这种方式保持两者之间的映射,因为有时我会只请求子实体,在这种情况下,我可能希望将父实体连同它一起获取。

有谁知道如何正确地做到这一点?

4

2 回答 2

1

我想我看到你的“循环依赖”在这里发挥作用,但为了明确起见,这就是我认为会发生的事情。您在 ParentEntity 上调用 EntityToDto,而后者又在所有 ChildEntity 元素上调用 EntityToDto。这些 ChildEntity 元素中的每一个元素依次调用 ParentEntity 上的 EntityToDto,然后我们又回到了开始的地方。

如果是这种情况,我的建议会很简单:不要在父级上设置子实体 care EntityToDto。我会在树的根部解析,然后让下面的所有内容继续向下解析,直到树完成。

如果您这样做,它将阻止子实体将父实体分配给自己。如果您需要能够从子级遍历到父级,我会让父级在 EntityToDto 调用完成后将自己分配给子级作为父级。

于 2013-10-18T16:52:49.183 回答
0

在进一步考虑之后,我决定不要过度复杂化,而是不允许通过映射器获取子实体及其父实体,而是在我的服务层中为那些少数但特定的场景处理它。

任何有同样问题的人也可以查看我在 reddit 上创建的这个帖子以获取更多信息。

于 2013-10-18T19:48:19.273 回答