【问题标题】:Using AutoMapper to map Wrapper<T> to T' by convention按照约定使用 AutoMapper 将 Wrapper<T> 映射到 T'
【发布时间】:2015-05-07 09:13:03
【问题描述】:

我有一个服务,它将枚举值包装在 SafeEnum 类型中,以便在不违反合同的情况下添加新的枚举值。

这是一个例子:

public class Customer
{
  public int Id { get; set; }
  public SafeEnum<CustomerType> Type { get; set; }
}

public class CustomerModel
{
  public int Id { get; set; }
  public CustomerModelType Type { get; set; }
}

使用 AutoMapper 从 Customer 映射到 CustomerModel 时,有没有办法自动从 SafeEnum&lt;T&gt; 映射到 T',其中 T 是封装类型,T' 是模型中的匹配类型?

我知道这可以通过为每个相关的枚举类型进行配置来解决,但我正在寻找更优雅的解决方案。

【问题讨论】:

  • @zespri 不,它是 CustomerType 的模型版本,即另一个具有相同或相似值的枚举类型。我已经编辑了示例以反映这一点,感谢您指出。 (例子只是一个例子,并不反映我所拥有的真实类型)

标签: c# automapper


【解决方案1】:

我最近也遇到了同样的问题。据我所知,Automapper 没有对这种场景提供官方支持(文档中没有提到通用包装器或类似的东西,我找不到任何关于如何做到这一点的网络资源),但它可以一点点工作就可以完成。

首先您需要创建一个实现IObjectMapper 接口的类。这个接口有两个方法IsMatch(ResolutionContext context)Map(ResolutionContext context, IMappingEngineRunner mapper)

当映射两个对象时,Automapper 在内部使用IsMatch 方法来确定IObjectMapper 的给定实例是否可用于从源类型映射到目标类型。在 ResolutionContext 对象上,您有 SourceType、DestinationType、SourceValue、DestinationValue、MappingEngine 的一个实例以及其他可以帮助您确定是否可以使用当前映射器映射这两种类型的东西。

Map 方法负责两种类型之间的实际映射。

因此,在IsMatch 方法中,您应该检查源类型或目标类型是否是您的包装类的实例。然后,在Map 方法上,当从包装后的值映射时,您可以通过反射解包该值,并使用 ResolutionContext 上提供的映射引擎将解包后的值映射到它的目标类型,然后返回它。

同样,当从任何类型映射到包装类型时,您可以获得封闭的泛型包装器的类型参数,使用解析上下文中提供的映射引擎从源类型映射到您的泛型所包含的类型包装器,并将结果包装在适当类型的包装器类的实例上。

最后,您需要在应用程序启动时配置 MappingEngine 时包含此映射器(这不适用于 Mapper 类的静态方法,因为您无法更改其上的默认映射器),如下所示:

var configuration = new ConfigurationStore(new TypeMapFactory(), new IObjectMapper[] { new WrapperMapper()}.Union(MapperRegistry.Mappers));
        var engine = new MappingEngine(configuration);    

MapperRegistry.Mappers 静态属性是所有默认 Automapper 映射器的集合。如果不包括这些,您将失去所有默认功能。

最后,这是一个有效的小提琴: https://dotnetfiddle.net/vWmRiY

它可能需要一些工作来适应您的特定用例,但总体思路就在那里。这可用于包装原始类型、复杂类型或自动映射器支持的任何内容。

【讨论】:

    猜你喜欢
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2019-07-16
    相关资源
    最近更新 更多