I have an entity:
public class Tag {
public int Id { get; set; }
public string Word { get; set; }
// other properties...
// and a collection of blogposts:
public ICollection<Post> Posts { get; set; }
}
and a model:
public class TagModel {
public int Id { get; set; }
public string Word { get; set; }
// other properties...
// and a collection of blogposts:
public int PostsCount { get; set; }
}
and I query the entity like this (by EF or NH):
var tagsAnon = _context.Tags
.Select(t => new { Tag = t, PostsCount = t. Posts.Count() })
.ToList();
Now, how can I map the tagsAnon
(as an anonymous object) to a collection of TagModel
(e.g. ICollection<TagModel>
or IEnumerable<TagModel>
)? Is it possible?
Yes, it is possible. You would have to use the DynamicMap method of the Automapper's Mapper class for each anonymous object you have. Something like this:
var tagsAnon = Tags
.Select(t => new { t.Id, t.Word, PostsCount = t.Posts.Count() })
.ToList();
var tagsModel = tagsAnon.Select(Mapper.DynamicMap<TagModel>)
.ToList();
Update: DynamicMap is now obsolete.
Now you need to create a mapper from a configuration that sets CreateMissingTypeMaps
to true
:
var tagsAnon = Tags
.Select(t => new { t.Id, t.Word, PostsCount = t.Posts.Count })
.ToList();
var config = new MapperConfiguration(cfg => cfg.CreateMissingTypeMaps = true);
var mapper = config.CreateMapper();
var tagsModel = tagsAnon.Select(mapper.Map<TagModel>)
.ToList();
I am not entirely sure if this is possible. Suggestions:
Why can't you just do this:
var tagsAnon = _context.Tags
.Select(t => new TagModel { Tag = t, PostsCount = t. Posts.Count() })
.ToList();
This SHOULD work, however it fails (I have read that DynamicMap is iffy on collections.
var destination = Mapper.DynamicMap<IEnumerable<TagModel>>(tagsAnon);
This proves that DynamicMap does work with anon types, just not seemingly with enumerables:
var destination = Mapper.DynamicMap<TagModel>(tagsAnon);
You can create a custom function to achieve this with latest Automapper. It uses the CreateMissingTypeMaps
property as mentioned in other answers above.
public static List<T> MapDynamicList<T>(IEnumerable<object> obj)
{
var config = new MapperConfiguration(c => c.CreateMissingTypeMaps = true);
var mapper = config.CreateMapper();
var newModel = obj.Select(mapper.Map<T>).ToList();
return newModel;
}
Then you just call the function with this single line of code:
var viewModel = Models.Helper.MapDynamicList<MatchSubCategory>(model);
where model
is the IEnumerable<object>
or List<object>
.