InvalidCastException while Mapping types MyType to MyType

499 Views Asked by At

I'm using AutoMapper 2.2.1 to map different business objects to view models. Now I'm getting a InvalidCastExceptions if I try to map objects which have a property of type CustomList (see code below). The exception says that CustomList cannot be casted to IList. Which is correct because CustomList implements IReadOnlyList and not IList.

So why automapper tries to cast it in this manner and how to fix/workaround this?

I have these types:

public class MyViewModel : SomeModel { //... some addtional stuff ...}

public class SomeModel {
public CustomList DescriptionList { get; internal set; }
}

public class CustomList : ReadOnlyList<SomeOtherModel> {}

public abstract class ReadOnlyList<TModel> : IReadOnlyList<TModel> {}

//map it
//aList is type of SomeModel 
var viewList = Mapper.Map<List<MyViewModel>>(aList);
1

There are 1 best solutions below

1
On

Having your class implement from IReadOnlyList is most likely causing the problem. Automapper doesn't know how to map a read-only list to a read-only list. It creates new instances of objects, and there is no add method or collection initializer for IReadOnlyList. Automapper needs to be able to access the underlying list the readonly list is wrapping around. This can be done using the ConstructUsing method.

Updated List Model:

public class CustomList : IReadOnlyList<string>
{
    private readonly IList<string> _List;

    public CustomList (IList<string> list)
    {
        _List = list;
    }

    public CustomList ()
    {
        _List = new List<string>();
    }

    public static CustomList CustomListBuilder(CustomList customList)
    {
        return new CustomList (customList._List);
    }
}

Updated automapper config

Mapper.CreateMap<CustomList, CustomList>().ConstructUsing(CustomList.CustomListBuilder);

This is a simple example but I was able to get it to map properly as well as not throw an exception. This isn't the best code, doing this would result in the same list being referenced by two different readonly lists (depending on your requirements, that may or may not be okay). Hopefully this helps.