Подтвердить что ты не робот

Как я могу сопоставить между двумя перечислениями с помощью Automapper?

У меня есть открытый интерфейс, который я пытаюсь сопоставить двум различным перечислениям друг с другом. Я попытался использовать следующий код:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>();

Если это не помогло, я попробовал:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>().ConvertUsing(x => (Common.ValidationResultType)((int)x));

Но это тоже не работает. Есть ли способ заставить automapper обрабатывать этот сценарий?

4b9b3361

Ответ 1

Вам не нужно создавать CreateMap для типов перечислений. Просто избавитесь от вызова CreateMap и он должен работать, если имена и/или значения совпадают между типами перечисления.

Ответ 2

В качестве альтернативы написанию пользовательских преобразователей просто используйте ConvertUsing()

Mapper.CreateMap<EnumSrc, EnumDst>().ConvertUsing(value => 
{
    switch(value)
    {
        case EnumSrc.Option1:
            return EnumDst.Choice1;
        case EnumSrc.Option2:
            return EnumDst.Choice2;
        case EnumSrc.Option3:
            return EnumDst.Choice3;
        default:
            return EnumDst.None;
    }
});

Ответ 3

My Automapper работает следующим образом:

Если я создаю карту: Automapper будет соответствовать перечислениям по значению, даже если имя идеально соответствует.

Если я не создаю карту: Automapper будет соответствовать перечислениям по имени.

Ответ 4

Самый простой способ Я нашел, что работа для меня такова:

My Enum является вложенным в другой класс, поэтому я использую метод ForMember и MapFrom, как показано ниже:

 Mapper.CreateMap<ProblematicCustomer, ProblematicCustomerViewModel>()                
            .ForMember(m=> m.ProblemType, opt=> opt.MapFrom(x=> (ProblemTypeViewModel)(int)x.ProblemType))
            .ForMember(m=> m.JudgmentType, opt=> opt.MapFrom(x=> (JudgmentTypeViewModel)(int)x.JudgmentType));

TypeType и JudgmentType - это перечисления. И связанные с ними модели для просмотра - это модели ProblemTypeViewModel и JudgmentTypeViewModel с теми же элементами, что и связанные с ними модели.

Хотя я не тестирую, но я думаю, что ниже строка должна работать для вас:

Mapper.CreateMap<Contract_1_1_0.ValidationResultType, Common.ValidationResultType>()
           .ForMember(m=> m, opt => opt.MapFrom(x=> (Common.ValidationResultType)(int)x);

Надеюсь, что это поможет.

Ответ 5

Здесь есть одна возможность для преобразования между двумя типами Enum, которые имеют разные значения, при этом все еще используют AutoMapper. В моем случае мне нужно было использовать AutoMapper, потому что типы Enum были свойствами для других объектов, преобразованных AutoMapper; использование AutoMapper для этих объектов было требованием.

Первым шагом является настройка конфигурации Mapper следующим образом:

Mapper.CreateMap<EnumSrc, EnumDst>()
    .ConstructUsing(EnumConversion.FromSrcToDst);

Вызов .ConstructUsing(...) позволяет нам передать наш собственный метод для преобразования. Метод преобразования довольно прямолинейный:

public class EnumConversion
{
    internal static EnumDst FromSrcToDst(ResolutionContext arg)
    {
        EnumSrc value = (EnumSrc)arg.SourceValue;
        switch(value)
        {
            case EnumSrc.Option1:
                return EnumDst.Choice1;
            case EnumSrc.Option2:
                return EnumDst.Choice2;
            case EnumSrc.Option3:
                return EnumDst.Choice3;
            default:
                return EnumDst.None;
        }
    }
}

Мы просто switch через значения источника Enum и произвольно возвращаем соответствующее значение Enum назначения. AutoMapper заботится обо всем остальном.

Ответ 6

Другие ответы здесь не спомогли мне.

Вам нужно создать класс, который реализует:

ITypeConvertor<SourceType ,DestinationType>

Так в качестве примера

 Mapper.CreateMap<EnumType1.VatLevel, EnumType2.VatRateLevel>()
       .ConvertUsing(new VatLevelConvertor());

И класс:

internal class VatLevelConvertor : ITypeConverter<EnumType1.VatLevel, EnumType2.VatRateLevel>
{
    public EnumType2.VatRateLevel Convert(ResolutionContext context)
    {
        EnumType1.VatLevel value = (EnumType1.VatLevel)context.SourceValue;
        switch (value)
        {
            case EnumType1.VatLevel.Standard:
                return EnumType2.VatRateLevel.Normal;
            case EnumType1.VatLevel.Reduced:
                return EnumType2.VatRateLevel.Lower;
            case EnumType1.VatLevel.SuperReduced:
                return EnumType2.VatRateLevel.Other;
            default:
                return EnumType2.VatRateLevel.Other;
        }
    }
}

Ответ 7

Просто создайте картограф для двух Enums, чтобы он! Automapper будет отображать либо значение соответствия, либо значение индекса Enum. (например, Черновик → Шаг 1)

public enum SourceStatus
{
    Draft,
    Submitted,
    Deleted
}

public enum DestinationStatus
{
    Step1,
    Step2,
    Step3
}

public class SourceObj
{
    public SourceStatus Status { get; set; }
}

public class DestinationObj
{
    public DestinationStatus Status { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        //Static APi style - this is obsolete now. From Version 5.0 onwards    this will be removed.
        SourceObj mySrcObj = new SourceObj();
        mySrcObj.Status = SourceStatus.Deleted;

        Mapper.CreateMap<SourceStatus, DestinationStatus>();
        Mapper.CreateMap<SourceObj, DestinationObj>();

        DestinationObj myDestObj = Mapper.Map<SourceObj, DestinationObj>(mySrcObj);

        //New way of doing it
        SourceObj mySrcObj2 = new SourceObj();
        mySrcObj2.Status = SourceStatus.Draft;

        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<SourceObj, DestinationObj>();
        });

        IMapper mapper = config.CreateMapper();
        var source = new SourceObj();
        var dest = mapper.Map<SourceObj, DestinationObj>(source);



    }
}

Ответ 8

Я пытался сопоставить "равные" перечисления с помощью Automapper, но, к сожалению, это не сработало. Я подозреваю, что проблема заключается в различии в корпусе:

public enum Foo {
    val1,
    val2
}

public enum Bar {
    Val1,
    Val2
}

Foo - это что-то автоматически генерируемое из XSD, и поставщик отстой. Также есть значения тридцать-то, и я не хотел ставить switch что-то большое для чего-то такого глупого.

Подход, который я принял, состоял в том, чтобы преобразовать исходное значение в строку и проанализировать его как значение назначения:

static Foo ConvertEnum(Bar source)
{
    Foo result;
    var parsed = Enum.TryParse(source.ToString().ToLowerInvariant(), true, out result);
    if(!parsed)
         // throw or return default value
         throw new ArgumentOutOfRangeException("source", source, "Unknown source value");
    return result;
}

Конечно, это работает только в том случае, если ваши перечисления имеют только различия в корпусе. Вы можете сделать его более сложным, очистив входную строку (например, удалите символы подчеркивания и т.д.) Или добавив к ней материал по мере необходимости.