Использование AutoMapper (v6.2.2, плюс AutoMapper.Extensions.Microsoft.DependencyInjection ) Я хочу использовать существующие системные TypeConverter
классы для преобразования из определенных моделей данных в строки.
Хотя внутренний MapperRegistry
содержит TypeConverterMapper
, который должен иметь возможность делать это автоматически ( без необходимости какой-либо ручной настройки здесь указано здесь ), он никогда не получит Вызывается как StringMapper
, имеет приоритет, когда типом назначения является string
.
Другие (более старые) ответы предлагают изменить объекты сопоставления в 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
.