我有一个服务,它将enum-values包装在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<T>
映射到T'
,其中T
是包装类型,T'
是模型中的匹配类型?
我知道可以通过配置每个相关的枚举类型来解决这个问题,但我正在寻找更优雅的解决方案。
答案 0 :(得分:0)
我最近遇到了同样的问题。从我收集的内容来看,Automapper没有这种场景的官方支持(没有提及通用包装或文档上的类似内容,我找不到任何有关如何操作的Web资源),但它可以通过一点点工作完成。
首先,您需要创建一个实现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
它可能需要一些工作来使其适应您的特定用例,但总的想法是存在的。这可以用于包装原始类型,复杂类型或者automapper支持的任何内容。