【问题标题】:How to map dynamic ViewModel List Type to DTO如何将动态 ViewModel 列表类型映射到 DTO
【发布时间】:2018-12-29 23:17:58
【问题描述】:

问题是将嵌套对象的动态列表映射到扁平 DTO。它包括嵌套对象的展平。还有就是接口类型。

Interface IfinalOutput
{
   object MainOutput;
   object CalcOutput;
   object SupportOutput;
}

class finalOutput<T,T2,T3> : IfinalOutput where T: IMainOutput, T2: ICalcOutput, T3: ISupportOutput
{
  public object MainOutput;
  public object CalcOutput;
  Public object SupportOutput;
  ...Other Properties
}

我们有多种具体类型的 IMainOutput、ICalcOutput、ISupportOutput 可以返回属于不同的源系统。 例如。 ABC系统有ABCMainOutput、ABCCalcOutput、ABCSupportOutput XYZ系统有XYZMainOutput、XYZCalcOutput等

现在我们为每个源系统都有 DTO,例如 ABCDto、XYZDto 类型的扁平结构。

问题是根据对象类型将 IEnumerable 序列化并映射到 IEnumerable 或 IEnumerable 并保持列表排序。

我尝试使用 Automapper,如下所示

public List<Tto> Serialize<Tfrom, Tto>(
        IEnumerable<IFinalOutput> outputTableCompositeViewModel)
{
   List<Tto> sourceSystemDTOList = new List<Tto>();
   AutoMapper.Mapper.Initialize(cfg => cfg.CreateMap<Tfrom, Tto>());
   foreach (var item in outputTableCompositeViewModel)
   {
     Tto outputItem = new Tto();              

     var outputTableItem = item.MainOutput;
     outputItem = AutoMapper.Mapper.Map<Tto>(outputTableItem);
     var supportTableItem = item.SupportOuput;
     var calculatedTableItem = item.CalcOutput;

     sourceSystemDTOList.Add(outputItem);
   }
   return new List<Tto>(sourceSystemDTOList);
}

现在所有属性都没有映射。请指导如何将 calc 和支持输出映射到 Dto 并避免使用 forloop。我可以使用 Automapper 或 ValueInjector。需要一种有效的方法来做到这一点。

【问题讨论】:

  • 将 CreateMissingTypeMaps 设置为 false 并调用 AssertConfigurationIsValid。 AM 会告诉您缺少哪些地图。 AM 默认处理集合,因此不需要循环。
  • 如果您只需要使用 valueinjecter 进行展平,您可以致电 a.InejctFrom&lt;FlatLoopInjection&gt;(src),但对于集合,您必须自己进行循环

标签: c# serialization automapper flatten valueinjecter


【解决方案1】:

我实施了以下更改并且效果很好。

首先,我必须为所有具体的 IMainOutput 类创建映射, ICalcOutput、ISupportOutput 与特定的源系统如下:

 Mapper.Initialize(cfg =>
        {

            cfg.CreateMap<ABCMainOutput, ABCdto>();
            cfg.CreateMap<ABCCalcOutput, ABCdto>();
            cfg.CreateMap<ABCSupportOutput, ABCdto>();
        });

其次,我添加了一个自动映射器扩展:

 public static TDestination Map<TSource, TDestination>(
       this TDestination destination, TSource source)
    {
        return Mapper.Map(source, destination);
    }

最后,我使用上述扩展来序列化最终输出。

public List<Tto> Serialize<Tfrom, Tto>(
    IEnumerable<IFinalOutput> outputTableCompositeViewModel)
{
   List<Tto> sourceSystemDTOList = new List<Tto>();       
   foreach (var item in outputTableCompositeViewModel)
   {
    Tto outputItem = new Tto();              

    var outputTableItem = item.MainOutput;       
    var supportTableItem = item.SupportOuput;
    var calculatedTableItem = item.CalcOutput;
    outputItem = Mapper.Map<Tto>(outputTableItem)
                                        .Map(calculatedTableItem)
                                        .Map(supportTableItem);
    sourceSystemDTOList.Add(outputItem);
   }
  return new List<Tto>(sourceSystemDTOList);
}

解决方案有效。

【讨论】:

  • 我创建了一个属性 [ModelProperty(nameof(MyClass.MyProperty)] 然后通过反射创建了一个映射器,因此名称可以是动态的。我发现它更好,因为在大型团队中可以轻松创建错误因为开发人员忘记更新映射器类
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
  • 2022-10-22
  • 2019-09-26
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
相关资源
最近更新 更多