web-dev-qa-db-fra.com

Comment mapper entre deux énumérations à l'aide d'Automapper?

J'ai une interface publique que j'essaie de mapper deux énumérations différentes l'une à l'autre. J'ai essayé d'utiliser le code suivant:

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

Quand ça n'a pas marché, j'ai essayé:

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

Mais cela ne semble pas fonctionner non plus. Existe-t-il de toute façon un automappeur pour gérer ce scénario?

46
Jeffrey Lott

Vous n'avez pas besoin de créer CreateMap pour les types d'énumération. Débarrassez-vous simplement de l'appel CreateMap et cela devrait fonctionner, tant que les noms et/ou les valeurs correspondent entre les types d'énumération.

41
Jimmy Bogard

Alternativement à l'écriture de convertisseurs personnalisés, utilisez simplement 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;
    }
});
57
Thorsten Hüglin

Mon Automapper fonctionne de cette façon:

Si je crée une carte: Automapper fera correspondre les énumérations par valeur, même si le nom correspond parfaitement.

Si je ne crée pas de carte: Automapper fera correspondre les énumérations par leur nom.

10
Piotr Kwiatek

La manière la plus simple que j'ai trouvée pour moi est la suivante:

Mon Enum est imbriqué dans une autre classe, donc j'utilise la méthode ForMember et MapFrom comme ci-dessous:

 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));

ProblemType et JudgmentType sont des énumérations. Et leurs modèles de vue associés sont ProblemTypeViewModel et JudgmentTypeViewModel avec les mêmes membres que leurs modèles associés.

Bien que je ne teste pas, mais je pense que la ligne ci-dessous devrait fonctionner pour vous:

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

J'espère que ça aide.

4
mesut

Créez simplement un mappeur pour deux Enums, c'est tout! Automapper mappera par la valeur correspondante ou la valeur d'index de l'énumération. (par exemple, Brouillon -> Étape 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);



    }
}
3
Dhanuka777

Les autres réponses ici n'ont pas fonctionné pour moi.

Vous devez créer une classe qui implémente:

ITypeConvertor<SourceType ,DestinationType>

Donc, à titre d'exemple

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

Et la classe:

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;
        }
    }
}
3
Neil

Voici une possibilité pour effectuer une conversion entre deux types Enum qui ont tous deux des valeurs différentes, tout en utilisant AutoMapper. Dans mon cas, j'avais besoin d'utiliser AutoMapper car les types Enum étaient des propriétés sur d'autres entités converties par AutoMapper; l'utilisation d'AutoMapper pour ces entités était une exigence.

La première étape consiste à installer la configuration du mappeur comme suit:

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

L'appel de .ConstructUsing(...) nous permet de passer dans notre propre méthode pour faire la conversion. La méthode de conversion est assez simple:

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;
        }
    }
}

Nous avons simplement switch à travers les valeurs de l'énumération source et renvoyons arbitrairement la valeur Enum de destination appropriée. AutoMapper s'occupe du reste.

3
Trevor

J'essayais de mapper entre des énumérations "égales" en utilisant Automapper, mais malheureusement cela n'a pas fonctionné. Je soupçonne que le problème est une différence de boîtier:

public enum Foo {
    val1,
    val2
}

public enum Bar {
    Val1,
    Val2
}

Foo est quelque chose généré automatiquement à partir d'un XSD, et le fournisseur est nul. Il y a aussi une trentaine de valeurs et je ne voulais pas mettre un switch aussi grand n'importe où pour quelque chose de si idiot.

L'approche que j'ai adoptée était de convertir la valeur source en chaîne et de l'analyser en tant que valeur de destination:

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;
}

Bien sûr, cela ne fonctionne que si vos énumérations n'ont que des différences de boîtier. Vous pouvez le rendre plus élaboré en nettoyant la chaîne d'entrée (par exemple, supprimez les traits de soulignement, etc.) ou en y ajoutant des éléments si nécessaire.

2
MarioDS