0

我正在尝试将一个类映射Function到另一个名为FunctionDTOusing的类AutoMapper。这些类看起来像这样:

public class Function
{
     ...
     public int MasterFunctionId { get; set; }
     public Function MasterFunction { get; set; }
     ...
}

public class FunctionDTO
{
     ...
     public int MasterFunctionId { get; set; }
     public FunctionDTO MasterFunction { get; set; }
     ...
}

映射非常适用于诸如 的属性MasterFunctionId,但MasterFunction始终为空,即使Function对象在该属性中有值也是如此。

对映射器的调用通过以下方式完成(PS 变量 config 被注入到类中):

query.ProjectTo<FunctionModel>(config)

我无法使用以下内容,因为我收到一条错误消息,可能是因为 Mapper 未初始化:

CreateMap<FLHFunction, FunctionModel>()
    .ForMember(f => f.PRNummerMaster, opt => opt.MapFrom(src => Mapper.Map<FLHFunction, FunctionModel>(src)));

有什么方法可以配置映射以使其工作?我对上一段代码尝试了类似的解决方案,但我一定遗漏了一些东西。

4

3 回答 3

1

我调查了一下,不幸的是,这(即自引用、递归映射)似乎不适用于ProjectTo().

几个 GitHub 问题:

https://github.com/AutoMapper/AutoMapper/issues/3195 https://github.com/AutoMapper/AutoMapper/issues/2171 https://github.com/AutoMapper/AutoMapper/issues/1149

JBogard 似乎总是建议为每个级别使用明确命名的分层 DTO。使用这种方法,解决问题非常简单(假设您只想要例如 2 个级别)。

例如:

    public class Function
    {
         public int MasterFunctionId { get; set; }
         public Function MasterFunction { get; set; }
    }

    public class FunctionChildDTO : FunctionDTO {}
    
    public class FunctionDTO
    {
         public int MasterFunctionId { get; set; }
         public FunctionChildDTO MasterFunction { get; set; }
    }

    ...
    
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Function, FunctionDTO>();
        cfg.CreateMap<Function, FunctionChildDTO>();
        
    });

但是希望我错了,有人能够提供适当的解决方案。同时,我将把这个答案留在这里以供参考。

于 2021-02-28T21:53:42.440 回答
0

据我所知,Automapper 不支持通过投影的直接自引用映射。文档对此有点模糊,因为您似乎只是缺少MaxDepth递归关联的配置选项,但我对其进行了相当彻底的测试,虽然它适用于.Map(),但它似乎根本不起作用.ProjectTo()即使文档表明这PreserveReferences不适用于ProjectTo()MaxDepth确实适用。

起作用的是构建 DTO 以反映层次结构。例如,而不是:

public class FunctionDTO
{
     ...
     public int? MasterFunctionId { get; set; }
     public FunctionDTO MasterFunction { get; set; }
}

对于 1 级自我参考,您可以使用:

public class FunctionDTO
{
     ...
     public int? MasterFunctionId { get; set; }
     public MasterFunctionDTO MasterFunction { get; set; }
}

public class MasterFunctionDTO : FunctionDTO
{
    public new FunctionDTO MasterFunction 
    { 
        get{ return null;} 
    }
}  

您的配置将 Function 映射到 FunctionDTO 和 MasterFunctionDTO 的位置​​。DTO 中的字段基本相同。MasterFunctionDTO 的 MasterFunction不会被填充,因此为清楚起见,它的配置选项应设置为Ignore().

对于 2 个层次结构:

public class FunctionDTO
{
     ...
     public int? MasterFunctionId { get; set; }
     public MasterFunctionDTO MasterFunction { get; set; }
}

public class MasterFunctionDTO : FunctionDTO
{
    public new MasterMasterFunctionDTO MasterFunction {get; set;}
}    

public class MasterMasterFunctionDTO : FunctionDTO
{
    public new FunctionDTO MasterFunction 
    { 
        get{ return null;} 
    }
}

将所有 3 个 DTO 映射回 Function 并将最终级别的“Master”属性设置为 Ignore。Automapper 可以解析这些引用并对其进行投影。

于 2021-02-28T22:49:33.470 回答
0

您还需要映射属性类,但由于它引用自身,因此不可能将递归类映射到自身。

    public class Function
{
     ...
     public int MasterFunctionId { get; set; }
     public ClassA MasterFunction { get; set; }
     ...
}

public class FunctionDTO
{
     ...
     public int MasterFunctionId { get; set; }
     public ClassB MasterFunction { get; set; }
     ...
}

您必须首先映射嵌套类 CreateMap<ClassA,ClassB>()

然后您可以映射包装类,然后可以使用以前的映射。

于 2021-02-28T18:42:52.137 回答