简体   繁体   English

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

[英]Map to specific derived type based on value on source using Automapper

I'm having trouble implementing Automapper conversion in a situation where the source is a class which should be mapped to one of two derived classes based on a value on the source. 在源是一个应根据源值映射到两个派生类之一的类的情况下,实现Automapper转换时遇到麻烦。

Here's a simplification of my 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
}

I'm using non-static Automapper so I create a MapperConfiguration from several Profiles at boot and inject the IMapper instance into my DI-container. 我使用的是非静态Automapper,因此我在启动时根据多个配置文件创建了一个MapperConfiguration,并将IMapper实例注入到我的DI容器中。 I want Automapper to map FooDTO to FooDerived1 when its Type property is "der1" and to FooDerived2 when it is "der2". 我希望Automapper将FooDTO的Type属性为“ der1”时映射到FooDerived1,而将其为“ der2”时映射​​到FooDerived2。

I've seen examples on this using the static api, something like this: 我已经看到了使用静态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));

This would map the Foo property of FooContainer to the correct derived type of FooBase. 这会将FooContainer的Foo属性映射到FooBase的正确派生类型。

But how can I do this without the static API? 但是,如何在没有静态API的情况下执行此操作? The IMapper instance is not yet created at the point of configuring the profile. 在配置文件时尚未创建IMapper实例。 Is there a way to leverage the overload of ConvertUsing() which takes a Func< ResolutionContext,object >? 有没有一种方法可以利用需要Func <ResolutionContext,object>的ConvertUsing()的重载? Can the resolution context give me whatever IMapper is currently being used? 解析上下文可以为我提供当前正在使用的IMapper吗? I've been looking, but can't find anything usable. 我一直在寻找,但是找不到任何可用的东西。

One way to get access to the mapping engine is via your own TypeConverter 一种访问映射引擎的方法是通过您自己的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);
}

You then create an actual implementation like: 然后,您创建一个实际的实现,例如:

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

Except instead of unwrapping an enum structure, you'd check the type and call Map with different types. 除了不解开枚举结构外,您还要检查类型并使用其他类型调用Map。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM