AutoMapper中的自定义对象到字符串映射器

时间:2018-05-09 09:13:07

标签: c# automapper

使用AutoMapper(v6.2.2,加上 AutoMapper.Extensions.Microsoft.DependencyInjection )我想使用现有的系统TypeConverter类将某些数据模型转换为字符串。

虽然内部MapperRegistry包含TypeConverterMapper应该能够自动执行此操作(而不需要任何手动配置,但是here),永远不会调用它,因为当目标类型为StringMapperstring优先。

其他(较旧的)答案建议更改MapperRegistry中的地图对象,但此类似乎已成为internal

我可以在AutoMapper中更改(或删除)不同的内置映射器类的优先级吗?

作为一种解决方法,我还尝试在我的Profile中创建一个地图,尝试使用类型转换器将任何对象转换为字符串:

private class ApiTypeConverter : ITypeConverter<object, string>
{
     public string Convert(object source, string destination, ResolutionContext context)
     {
        TypeConverter sourceTypeConverter = TypeDescriptor.GetConverter(source.GetType());
        if (sourceTypeConverter.CanConvertTo(typeof(string)))
        {
           return (string)sourceTypeConverter.ConvertTo(source, typeof(string));
        }

        return default(string);
     }
}

我配置为使用:

CreateMap<object, string>().ConvertUsing<ApiTypeConverter>();

但这也没有像预期的那样奏效。理想情况下,我只对可以使用条件转换的成员执行此操作,例如:

ForAllMaps((m, e) => e.ForAllMembers(opt => opt.Condition(HasConverter))
                      .ConvertUsing<ApiTypeConverter>());

但是,这是不可能的(ForAllMembers方法返回void)。

当我使用 AutoMapper.Extensions.Microsoft.DependencyInjection 时,我能够使用additionalInitAction参数来更改映射器:

services.AddAutoMapper(InitAction, GetType().Assembly);

private void InitAction(IMapperConfigurationExpression configuration)
{
    var mapper = configuration.Mappers.OfType<StringMapper>().First();
    configuration.Mappers.Remove(mapper);
}

这导致一切按预期工作,但似乎有些黑客,因为其他地图可能依赖于StringMapper

2 个答案:

答案 0 :(得分:1)

您可以使用configuration.Mappers更改内置映射器&#39;列表,但是从对象到字符串的映射也应该有用。

Mapper.Initialize(cfg =>
{
    var mappers = cfg.Mappers;
});

答案 1 :(得分:1)

如果使用依赖注入,则可以在将AutoMapper添加到服务时更改配置:

services.AddAutoMapper(InitializeMapper, typeof(Startup).Assembly);

然后添加适当的初始化:

private static void InitializeMapper(IMapperConfigurationExpression cfg)
{
    StringMapper stringMapper = cfg.Mappers.OfType<StringMapper>().First();
    int index = cfg.Mappers.IndexOf(stringMapper);

    cfg.Mappers.Insert(index, new CustomObjectMapper());
}