【问题标题】:Mapping one source class to multiple derived classes with automapper使用自动映射器将一个源类映射到多个派生类
【发布时间】:2013-01-20 05:37:14
【问题描述】:

假设我有一个源类:

public class Source
{
    //Several properties that can be mapped to DerivedBase and its subclasses
}

还有一些目的地类:

public class DestinationBase
{
     //Several properties
}

public class DestinationDerived1 : DestinationBase
{
     //Several properties
}

public class DestinationDerived2 : DestinationBase
{
     //Several properties
}

那我希望派生的目标类继承基类的automapper配置,因为我不想重复,有什么办法可以实现吗?

Mapper.CreateMap<Source, DestinationBase>()
    .ForMember(...)
    // Many more specific configurations that should not have to be repeated for the derived classes
    .ForMember(...);

Mapper.CreateMap<Source, DestinationDerived1 >()
    .ForMember(...);
Mapper.CreateMap<Source, DestinationDerived2 >()
    .ForMember(...);

当我这样写它时,它根本不使用基本映射,并且 include 似乎对我没有帮助。

编辑: 这是我得到的:

public class Source
{
    public string Test { get; set; }
    public string Test2 { get; set; }
}

public class DestinationBase
{
    public string Test3 { get; set; }
}

public class DestinationDerived1 : DestinationBase
{
    public string Test4 { get; set; }
}

public class DestinationDerived2 : DestinationBase
{
    public string Test5 { get; set; }
}

Mapper.CreateMap<Source, DestinationBase>()
              .ForMember(d => d.Test3, e => e.MapFrom(s => s.Test))
              .Include<Source, DestinationDerived1>()
              .Include<Source, DestinationDerived2>();

        Mapper.CreateMap<Source, DestinationDerived1>()
              .ForMember(d => d.Test4, e => e.MapFrom(s => s.Test2));

        Mapper.CreateMap<Source, DestinationDerived2>()
              .ForMember(d => d.Test5, e => e.MapFrom(s => s.Test2));

AutoMapper.AutoMapperConfigurationException : 未映射的成员被发现。查看以下类型和成员。

添加自定义映射表达式、忽略、添加自定义解析器或修改源/目标类型

Source -> DestinationDerived1(目标成员列表)

测试3

【问题讨论】:

标签: c# automapper automapper-2


【解决方案1】:

将派生映射包含到基本映射中:

Mapper.CreateMap<Source, DestinationBase>()
    .ForMember(d => d.Id, op => op.MapFrom(s => s.Id)) // you can remove this
    .Include<Source, DestinationDerived1>()
    .Include<Source, DestinationDerived2>();

Mapper.CreateMap<Source, DestinationDerived1>()
    .ForMember(d => d.Name, op => op.MapFrom(s => s.Text))
    .ForMember(d => d.Value2, op => op.MapFrom(s => s.Amount));

Mapper.CreateMap<Source, DestinationDerived2>()
    .ForMember(d => d.Value, op => op.MapFrom(s => s.Amount));

用法:

Mapper.AssertConfigurationIsValid();
var s = new Source() { Id = 2, Amount = 10M, Text = "foo" };
var d1 = Mapper.Map<DestinationDerived1>(s);
var d2 = Mapper.Map<DestinationDerived2>(s);

请参阅 AutoMapper wiki 上的 Mapping inheritance


更新:这里是完整的类代码。

public class Source
{
    public int Id { get; set; }
    public string Text { get; set; }
    public decimal Amount { get; set; }
}

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

public class DestinationDerived1 : DestinationBase
{
    public string Name { get; set; }
    public decimal Value2 { get; set; }
}

public class DestinationDerived2 : DestinationBase
{
    public decimal Value { get; set; }
}

更新(AutoMapper 错误的解决方法):

public static class Extensions
{
    public static IMappingExpression<Source, TDestination> MapBase<TDestination>(
        this IMappingExpression<Source, TDestination> mapping)
        where TDestination: DestinationBase
    {
        // all base class mappings goes here
        return mapping.ForMember(d => d.Test3, e => e.MapFrom(s => s.Test));
    }
}

以及所有映射:

    Mapper.CreateMap<Source, DestinationBase>()
          .Include<Source, DestinationDerived1>()
          .Include<Source, DestinationDerived2>()
          .MapBase();

    Mapper.CreateMap<Source, DestinationDerived1>()
          .MapBase()
          .ForMember(d => d.Test4, e => e.MapFrom(s => s.Test2));

    Mapper.CreateMap<Source, DestinationDerived2>()
          .MapBase()
          .ForMember(d => d.Test5, e => e.MapFrom(s => s.Test2));

【讨论】:

  • 这实际上是我尝试过的,但它似乎不起作用,我有一个运行 AsserConfigurationIsValid 的单元测试,它说我在 DestinationBase 中映射的属性没有为 DestinationDerived 类设置。
  • @ErikNordenhök 刚刚验证 - 工作正常。 Mapper.AssertConfigurationIsValid() 表示配置有效
  • 无法将我的代码发布在我运行的内容和我得到的错误上,因为评论太长了,但是我看不出与您的答案和我编辑的示例有什么不同原始帖子但是我的配置无效。
  • @ErikNordenhök 为什么您将我的答案发布到您的问题中?顺便说一句,原因可能是将相同的源属性映射到不同的目标属性。我会检查的
  • @ErikNordenhök 我已经复制了您的问题。我认为这是 AutoMapper 的错误。我看到重用映射的唯一解决方案是创建扩展方法,该方法将为基类进行映射。我会在一分钟内更新代码
【解决方案2】:

适用于 Automapper 8.0
当前版本有新方法IncludeAllDerived
这是工作示例:

        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Source, DestinationBase>()
                .ForMember(dest => dest.Test3, opt => opt.MapFrom(src => src.Test))
                .IncludeAllDerived();

            cfg.CreateMap<Source, DestinationDerived1>()
                .ForMember(dest => dest.Test4, opt => opt.MapFrom(src => src.Test2));

            cfg.CreateMap<Source, DestinationDerived2>()
                  .ForMember(dest => dest.Test5, opt => opt.MapFrom(src => src.Test2));
        });

        var mapper = config.CreateMapper();

        var source = new Source { Test = "SourceTestProperty", Test2 = "SourceTest2Property" };
        var d1 = mapper.Map<DestinationDerived1>(source);
        var d2 = mapper.Map<DestinationDerived2>(source);

        Assert.Equal("SourceTestProperty", d1.Test3);
        Assert.Equal("SourceTest2Property", d1.Test4);

        Assert.Equal("SourceTestProperty", d2.Test3);
        Assert.Equal("SourceTest2Property", d2.Test5);

【讨论】:

    【解决方案3】:

    注意!对于那些对派生接口有问题的人。 AutoMapper 不支持注册派生接口。只处理类。

    要使其工作,您必须将 CreateMap 的类型引用更改为类而不是接口。

    例子:

    interface Interface1 {}
    class Class1: Interface1 {}
    interface Interface2: Interface1 {}
    class Class2: Class1, Interface2 {}
    
    CreateMap<OtherClass, Interface1>().IncludeAllDerived();
    CreateMap<OtherClass, Interface2>();
    

    任何针对 Interface2 的映射将只使用第一个 CreateMap。您必须将第二个标识为

    CreateMap<OtherClass, Class2>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-09
      • 2021-08-04
      相关资源
      最近更新 更多