2012-06-29 5 views
29

Ich habe eine öffentlich zugängliche Schnittstelle, die ich versuche, zwei verschiedene Aufzählungen einander zuzuordnen. Ich habe versucht, den folgenden Code zu verwenden:Wie kann ich mit Automapper zwischen zwei enums mappen?

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

Wenn das nicht funktioniert, habe ich versucht:

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

Aber das scheint nicht zu funktionieren. Gibt es überhaupt einen automatischen Treiber, um dieses Szenario zu bewältigen?

+0

Haben Sie eine Fehlermeldung erhalten? Was hat nicht funktioniert? –

+0

Ich habe eine "Fehlende Typ-Map-Konfiguration oder nicht unterstützte Zuordnung" erhalten. Error. –

+3

Können Sie Ihre Enums posten? –

Antwort

33

CreateMap für Enum-Typen ist nicht erforderlich. Entfernen Sie einfach den CreateMap-Aufruf, und es sollte funktionieren, solange die Namen und/oder Werte zwischen Aufzählungstypen übereinstimmen.

+0

Wenn diese Vorgehensweise befolgt wird, wird sie dann mit Enum-Wert oder Mitgliedsnamen angepasst? –

+9

Was passiert, wenn die Namen und Werte nicht übereinstimmen? – Darcy

+1

Dann müssten Sie einen benutzerdefinierten Typkonverter erstellen. –

2

Hier ist eine Möglichkeit für eine Konvertierung zwischen zwei Enum-Typen, die beide unterschiedliche Werte haben, während Sie immer noch AutoMapper verwenden. In meinem Fall musste ich AutoMapper verwenden, da die Enum-Typen Eigenschaften für andere Objekte waren, die von AutoMapper konvertiert wurden. Die Verwendung von AutoMapper für diese Entitäten war eine Voraussetzung.

Der erste Schritt ist die Mapper-Konfiguration wie so einrichten:

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

Aufruf .ConstructUsing(...) ermöglicht es uns, in unserer eigenen Methode zu übergeben, um die Umwandlung zu machen. Das Verfahren zur Umwandlung ist ziemlich geradlinig:

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

Wir haben einfach switch durch die Werte der Quelle Enum und willkürlich den entsprechenden Ziel Enum Wert zurück. AutoMapper kümmert sich um den Rest.

+1

Ich habe versucht, diese Implementierung und es nur basierend auf dem Integer-Wert (AutoMapper 3.3.1) zugeordnet. Ich werde meine Antwort hinzufügen, die unten funktioniert hat – Neil

2

Die anderen Antworten hier funktionierten nicht für mich.

Sie müssen eine Klasse erstellen, die implementiert:

ITypeConvertor<SourceType ,DestinationType> 

So als Beispiel

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

und die Klasse:

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

Alternativ benutzerdefinierten Konverter zu schreiben, benutzen Sie einfach 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; 
    } 
}); 
4

Der einfachste Weg, fand ich, dass die Arbeit für mich ist, wie folgt:

Meine Enum ein in einer anderen Klasse geschachtelt ist so verwende ich ForMember Methode und MapFrom wie folgt:

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

The ProblemType und JudgmentType sind Enums. Und die zugehörigen View-Modelle sind ProblemTypeViewModel und JudgmentTypeViewModel mit denselben Membern wie ihre verwandten Modelle.

Obwohl ich nicht testen, aber ich denke, unterhalb der Linie sollte für Sie arbeiten:

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

Hoffe, dass es Hilfe.

2

Ich habe versucht, mit Automapper zwischen "gleichen" enums zu mappen, aber leider hat es nicht funktioniert. Ich vermute, dass das Problem ein Unterschied im Gehäuse ist:

public enum Foo { 
    val1, 
    val2 
} 

public enum Bar { 
    Val1, 
    Val2 
} 

Foo ist etwas automatisch generiert aus einem XSD, und der Lieferant saugt. Außerdem gibt es Werte um die Dreißig, und ich wollte keinen so großen Wert auf irgendwas setzen.

Der Ansatz, den ich nahm, war die Quelle Wert Zeichenfolge zu konvertieren und zu analysieren, dass als Zielwert:

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

Natürlich funktioniert dies nur, wenn Ihre Aufzählungen nur Unterschiede in Gehäusen. Sie könnten es ausführlicher machen, indem Sie die Eingabezeichenfolge bereinigen (z. B. Unterstriche entfernen usw.) oder indem Sie nach Bedarf etwas hinzufügen.

2

Erstellen Sie einfach einen Mapper für zwei Enums, das war's! Automapper mappt entweder den übereinstimmenden Wert oder den Indexwert der Enumeration. (Z Draft -> Schritt 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); 



    } 
} 
6

Meine AutoMapper funktioniert so:

Wenn ich eine Karte erstellen: AutoMapper Aufzählungen von Wert übereinstimmen, auch wenn Name Spiel perfekt.

Wenn ich keine Karte erstellen: Automapper wird enums mit Namen übereinstimmen.

Verwandte Themen