3
votes

While trying to translate between my ViewModel and my domain model using AutoMapper I noticed that it does not play well with Enums marked the the Flags attribute.

Here is a quick mockup of the classes:

ViewModel:

public class TestViewModel
{
    // array of individual Enum values
    public TestEnum[] TestEnum { get; set; } 
}

Domain Model:

public class TestModel
{
    // single Enum marked with flags attribute
    public TestEnum TestEnum { get; set; }
}

Enum:

[Flags]
public enum TestEnum
{
    Test1,
    Test2,
    Test3,
    Test4
}

This is what I am trying to do. I guess I need a Custom resolver of some sort in my Automapper config because it throws an exception when I do Mapper.Map().

My question: How would I accomplish this?

Bonus question: Is this best practice for handling Flags Enums / Bitmasks in Viewmodel -> Domain models (in a MVVM respect)? If not, what practice would you suggest (using AutoMapper or otherwise)?

2

2 Answers

1
votes

I'd skip AutoMapper and go the model binding route. If you're using ASP.NET MVC, you can hook directly into model binding so that all values are combined into one.

5
votes

When mapping to the view model, you can try to use Enum.GetValues() and LINQ to get a list of enum values. To map back to the model, try using Aggregate()...

Mapper.CreateMap<TestModel, TestViewModel>()
    .ForMember(v => v.TestEnum, 
        x => x.MapFrom(m => Enum.GetValues(typeof(TestEnum))
                            .Cast<TestEnum>()
                            .Where(e => (e & m) > 0)
                            .ToList()))
    .ReverseMap()
    .ForMember(m => m.TestEnum,
        x => x.MapFrom(v => v.Aggregate((i, j) => i | j));

As for whether this is the best approach, it really depends on how the view model is being used. Currently, the view model doesn't contain flags that aren't set; do you need them for rendering the view?