views:

134

answers:

2

Hi All,

I've found a couple of posts that describe similar scenarios to mine but nothing that has the same concept or has been resolved so I'm sure I will get complaints about this question but I still want to ask it so some of you more knowledgeable than my self can give me some advice.

My problem is hydrating a Viewmodel from a Linq2Sql object that has been returned from the database. We have done this in a few areas and have a nice layered pattern worked up for it but the latest item calls for some enums to be used and this has caused headaches all round. Currently we pull back from the database then use automapper to hydrate (or flattern) into our viewmodels but having the enums in the model seems to be causing issues with Automapper. I've tried to create custom resovlers which have sufficed for all my other mapping requirements but it doesn't work in this instance.

A sample of the Code looks like

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

I get the following error

[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

I'd like to stick with Automapper for all of our mapping actions but I've seen a lot of people say that it doesn't do this type of mappings so I'm starting to wonder if I'm abusing it in the wrong way? also I've seen a few mentions of ValueInjecter is this an alternative to Automapper or will it be usefull to just plug the holes in Automapper for the hydration of models and use Automapper for flatterning? opinions suggestions or even a solution would be much appreciated.

Yes I could just use a string in my ViewModel but I'm not a fan of magic strings.. (I can't spell and It causes me Problems).. and this particular Item is used by helpers to perform some logic in a number of places, plus I pay for VS license mainly so I can use intellisense so I want it wherever possible

Many Thanks

A: 

This is an issue with the automapper documenation. If you download the automapper source there are examples in there. The code you want will look like this:

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);
    }
}
Jason More
Thanks Jason.. I went to try you solution but I can't understand where the .Context.SourceValue and the source.New have come from? Am I missing soemthing.. sorry bit of a noob I know.
Andyroo
Hi Jason Thanks for the pointers if you see my comment above I got it sorted with out the need for custom resolvers. Thanks all the same and pointing me at the samples was a great help
Andyroo
Sure no problem!
Jason More
+1  A: 

here's a solution with the ValueInjecter: since you already solved the problem I'm just going to point you to something similar:

http://stackoverflow.com/questions/3462420/automapper-strings-to-enum-descriptions

in this question the requirements were a bit more than just doing from string to enum, but it includes this conversion also

about the ValueInjecter being an alternative: yes, it does stuff more generic no configuration for every little thing required, and build whatever convention you can imagine

Omu
Cheers for that I'll have a good look at it.
Andyroo