I updated from AutoMapper 2.0.0 to 2.2.0 today and realized the update broke some code. Wanted to ask about it here before posting as an issue on the automapper github site.
One of my destination types initializes a collection property like so:
public class PageOf<TModel>
{
public PageOf()
{
Items = Enumerable.Empty<TModel>();
}
public IEnumerable<TModel> Items { get; set; }
}
With automapper 2.0.0, this was fine. When I updated to 2.2.0, mapping to this destination type caused a NotSupportedException with the message "Collection was of a fixed size." (That exception was wrapped inside an AutoMapperMappingException.)
I was able to fix the issue by changing the constructor code above to this:
public PageOf()
{
Items = new List<TModel>();
}
It seems as if AutoMapper 2.0.0 was discarding whatever value was in the Items property and using the set
Property accessor, whereas AutoMapper 2.2.0 is just using the get
property accessor and trying to modify the existing IEnumerable. It looks like Enumerable.Empty<TModel>()
is just substituting a zero-length array, which would explain the exception.
Is this a bug? What in AutoMapper changed between 2.0.0 and 2.2.0 that would cause it to ignore the destination property setter and instead try to modify the existing collection?
Update:
As requested, here is the CreateMap call:
public class PagedQueryResultToPageOfItemsProfiler : Profile
{
protected override void Configure()
{
CreateMap<PagedQueryResult<EstablishmentView>, PageOfEstablishmentApiModel>();
}
}
The PageOfEstablishmentApiModel
class inherits from PageOf<EstablishmentApiModel>
.
Here is the Mapper.Map code:
var query = Mapper.Map<EstablishmentViewsByKeyword>(input);
var results = _queryProcessor.Execute(query);
var model = Mapper.Map<PageOfEstablishmentApiModel>(results); // exception here
If a special mapping configuration is necessary (for example .ConvertUsing(x => x)) in AutoMapper going from 2.0.0 to 2.2.0, we may have to hang onto the old version. I always liked how AM automatically converted collection properties, and without that, AM seems more like ValueInjecter.
Mapper.Map
method calls (are you using generic methods?). This is likely "by design" and easily reverted to your old behavior with the right mapper method or mapper configuration. You can return an array from automapper and assign it to your IEnumerable property as in the docs on github. I'll post an example or two as an answer once I see your code that performs the map. – Manger