使用 Automapper 根据源上的值映射到特定的派生类型

Map to specific derived type based on value on source using Automapper

在源是 class 的情况下,我无法实现 Automapper 转换,应该根据源上的值将其映射到两个派生的 classes 之一。

这是我的 classes 的简化版:

public class FooContainerDTO
{
    public FooDTO Foo { get; set; } 
}

public class FooDTO
{
    public string Type { get; set; }

    //some properties..
}

public class FooContainer
{
    public FooBase Foo { get; set; }
}

public abastract class FooBase
{
    //some properties..
}

public class FooDerived1 : FooBase
{
    //some properties
}

public class FooDerived2 : FooBase
{
    //some properties
}

我使用的是非静态 Automapper,因此我在启动时从多个配置文件创建了一个 MapperConfiguration,并将 IMapper 实例注入到我的 DI 容器中。 我希望 Automapper 在其类型 属性 为 "der1" 时将 FooDTO 映射到 FooDerived1,在其类型为 "der2".

时将其映射到 FooDerived2

我看过使用静态 api 的例子,像这样:

 Mapper.CreateMap<FooContainerDTO, FooContainer>();
        //ForMember configurations etc.

 Mapper.CreateMap<FooDTO, FooDerived1>();
        //ForMember configurations etc.

 Mapper.CreateMap<FooDTO, FooDerived2>();
        //ForMember configurations etc.

 Mapper.CreateMap<FooDTO, FooBase>()
       .ConvertUsing(dto => dto.Type == "der1"
           ? (FooBase) Mapper.Map<FooDerived1>(dto)
           : Mapper.Map<FooDerived2>(dto));

这会将 FooContainer 的 Foo 属性 映射到 FooBase 的正确派生类型。

但是如果没有静态 API 我怎么能这样做呢? IMapper 实例在配置配置文件时尚未创建。 有没有办法利用采用 Func 的 ConvertUsing() 的重载?解析上下文可以给我当前正在使用的任何 IMapper 吗?我一直在寻找,但找不到任何可用的东西。

访问地图引擎的一种方法是通过您自己的 TypeConverter

abstract class MyTypeConverter<TSource,TDestination> : ITypeConverter<TSource, TDestination>
{
    protected ResolutionContext context;
    public TDestination Convert(ResolutionContext context)
    {
        this.context = context;
        return Convert((TSource)context.SourceValue);
    }
    public abstract TDestination Convert(TSource source);
}

然后您创建一个实际的实现,例如:

class MyTypeMapper : MyTypeConverter<EnumType,EnumTypeView>
{
    public override EnumTypeView Convert(EnumType source)
    {
        return context.Engine.Mapper.Map<EnumTypeID, EnumTypeView>(source.EnumBaseType);
    }
}

除了不展开枚举结构外,您需要检查类型并使用不同类型调用 Map。