2010-09-20 22 views
8

Mon problème est un hydratant viewmodel d'un objet Linq2Sql qui a été renvoyé de la base de données. Nous l'avons fait dans quelques domaines et nous avons élaboré un joli modèle en couches, mais le dernier article demande l'utilisation de certains enums, ce qui a causé des maux de tête. Actuellement, nous retirons de la base de données, puis utilisons Automapper pour hydrater (ou aplatir) dans nos Viewmodels, mais les énumérations dans le modèle semblent causer des problèmes avec Automapper. J'ai essayé de créer des resovleurs personnalisés qui ont suffi pour tous mes autres besoins de mappage, mais cela ne fonctionne pas dans ce cas.chaîne de la carte à ENUM avec Automapper

Un échantillon du code ressemble:

public class CustomerBillingTabView{ 
    public string PaymentMethod {get; set;} 
    ...other details 
} 

public class BillingViewModel{ 
    public PaymentMethodType PaymentMethod {get; set;} 
    ...other details 
} 

public enum PaymentMethodType { 
    Invoice, DirectDebit, CreditCard, Other 
} 

public class PaymentMethodTypeResolver : ValueResolver<CustomerBillingTabView, PaymentMethodType> 
{ 
    protected override PaymentMethodType ResolveCore(CustomerBillingTabView source) 
    { 

     if (string.IsNullOrWhiteSpace(source.PaymentMethod)) 
     { 
      source.PaymentMethod = source.PaymentMethod.Replace(" ", ""); 
      return (PaymentMethodType)Enum.Parse(typeof(PaymentMethodType), source.PaymentMethod, true); 
     } 

     return PaymentMethodType.Other; 
    } 
} 

     CreateMap<CustomerBillingTabView, CustomerBillingViewModel>() 
     .ForMember(c => c.CollectionMethod, opt => opt.ResolveUsing<PaymentMethodTypeResolver>()) 

Je reçois l'erreur suivante

[ArgumentException: Type provided must be an Enum. 
Parameter name: enumType] 
    System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult) +9626766 
    System.Enum.Parse(Type enumType, String value, Boolean ignoreCase) +80 
    AutoMapper.Mappers.EnumMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) +231 
    AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) +720 

J'aimerais rester avec Automapper pour toutes nos actions de cartographie, mais je l'ai vu beaucoup de gens disent qu'il ne fait pas ce type de correspondance, alors je commence à me demander si je l'utilise mal. Aussi, j'ai vu quelques mentions de ValueInjecter - est-ce une alternative à Automapper, ou sera-t-il utile de simplement brancher les trous dans Automapper pour l'hydratation des modèles et utiliser Automapper pour aplatir?

Oui, je pourrais juste utiliser une chaîne dans mon ViewModel, mais je ne suis pas un fan de chaînes magiques, et cet article particulier est utilisé par les assistants pour effectuer une certaine logique dans un certain nombre d'endroits.

+0

D'oh après avoir regardé de plus près les exemples dans la source et mes modèles I réalisé quelques choses d'abord, pour une raison quelconque, j'avais rendu la propriété enum sur le ViewModel NULL qui a causé les problèmes principaux ?? !! La deuxième chose était que je n'avais pas considéré l'espace blanc retourné par notre vue "Direct Debit" aurait dû être DirectDebit .. Une fois que j'ai enlevé ces questions, Automapper a fait ses devoirs avec des résolveurs personnalisés etc .. Woo hoo –

+0

+1 pour mentionner ValueInjecter;) – Omu

Répondre

9

Ceci est un problème avec la documentation AutoMapper. Si vous téléchargez la source AutoMapper, vous trouverez des exemples. Le code que vous voulez ressemblera à ceci:

public class PaymentMethodTypeResolver : ValueResolver<CustomerBillingTabView, PaymentMethodType> 
{ 
    protected override PaymentMethodType ResolveCore(CustomerBillingTabView source) 
    { 

     string paymentMethod = source.Context.SourceValue as string; 

     if (string.IsNullOrWhiteSpace(paymentMethod)) 
     { 
      paymentMethod = paymentMethod.Replace(" ", ""); 
      return source.New((PaymentMethodType)Enum.Parse(typeof(PaymentMethodType), paymentMethod, true)); 
     } 

     return source.New(PaymentMethodType.Other); 
    } 
} 
+0

Merci Jason .. Je suis allé essayer votre solution mais je ne peux pas comprendre d'où viennent le .Context.SourceValue et le source.New? Est-ce que je manque quelque chose .. désolé peu d'un noob je sais. –

+0

Salut Jason Merci pour les pointeurs si vous voyez mon commentaire ci-dessus, je l'ai fait trier avec le besoin de résolveurs personnalisés. Merci tout de même et en me montrant les échantillons a été d'une grande aide –

+0

Sure aucun problème! –

5

est ici une solution avec le ValueInjecter: depuis que vous avez déjà résolu le problème que je vais juste vous indiquer quelque chose de similaire:

AutoMapper strings to enum descriptions

dans cette question, les exigences étaient un peu plus que de simplement faire de la chaîne en eNUM, mais il comprend aussi cette conversion

sur le ValueInjecter étant une alternative: oui, il fait des choses plus génériques aucune configuration pour chaque petite chose requise, et construis n'importe quelle convention que vous pouvez imaginer

+0

Bravo pour ça, je vais y jeter un coup d'œil. –