{"action":"created","issue":{"url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1300","repository_url":"https://api.github.com/repos/AutoMapper/AutoMapper","labels_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1300/labels{/name}","comments_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1300/comments","events_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1300/events","html_url":"https://github.com/AutoMapper/AutoMapper/issues/1300","id":156443527,"number":1300,"title":"AutoMapper 4.2.1 Abstract Mapping Issue","user":{"login":"mford9","id":19547656,"avatar_url":"https://avatars.githubusercontent.com/u/19547656?v=3","gravatar_id":"","url":"https://api.github.com/users/mford9","html_url":"https://github.com/mford9","followers_url":"https://api.github.com/users/mford9/followers","following_url":"https://api.github.com/users/mford9/following{/other_user}","gists_url":"https://api.github.com/users/mford9/gists{/gist_id}","starred_url":"https://api.github.com/users/mford9/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mford9/subscriptions","organizations_url":"https://api.github.com/users/mford9/orgs","repos_url":"https://api.github.com/users/mford9/repos","events_url":"https://api.github.com/users/mford9/events{/privacy}","received_events_url":"https://api.github.com/users/mford9/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2016-05-24T08:02:11Z","updated_at":"2016-05-24T13:23:15Z","closed_at":null,"body":"I’m currently having an issue with mapping a list of abstract types using AutoMapper.\r\n\r\nI have an abstract object called `BaseDomain`, which is derived by `DomainA` and `DomainB`. I also have the same structure for my data contracts with the suffix `Dto` at the end.\r\nI’m trying to use AutoMapper to map a list of `BaseDomain`s containing both `DomainA` and `DomainB` objects to the relevant data contracts. Previously I have achieved this by using the `Include` method.\r\n\r\nHowever, due to an important architecture change mappings that previously used the `Include` method have now stopped working and throw the following error ‘System.InvalidOperationException: Instances of abstract classes cannot be created.’\r\n\r\nI have tracked the issue down to a configuration issue. I have provided two examples below. Both scenarios are the same with the small exception of how AutoMapper is configured.\r\n\r\nScenario one configures AutoMapper configuration in the MappingConfiguration object delegate. This maps a list of `BaseDomain` objects correctly without throwing an exception. \r\n\r\nScenario two configures AutoMapper configuration after the MappingConfiguration delegate has been executed. This doesn’t map a list of `BaseDomain` objects and will throw the exception mentioned above however, this example will map a list of `DomainA` objects. \r\n\r\nI have provided the code for both scenarios below. Which were written in LINQPad4. The example is using AutoMapper 4.2.1. It would be really good if we could get scenario 2 to work correctly as this would then adhere to our architecture.\r\n\r\nScenario one: Works for abstract and non-abstract types\r\n```\r\n\r\nvoid Main()\r\n{\r\n\t\r\n\tIMapperConfiguration _mappingConfig = new MapperConfiguration(Configure);\t \r\n\tIMapper _objectMapper = ((MapperConfiguration)_mappingConfig).CreateMapper();\r\n\t\r\n\tvar baseDomainObjects = new List<BaseDomain>\r\n\t{\r\n\t\tnew DomainA { Id = 1, Text = \"Domain A\", ExtraPropertyA = \"A\" },\r\n\t\tnew DomainB { Id = 2, Text = \"Domain B\", ExtraPropertyB = \"B\" }\r\n\t};\r\n\t\r\n\tvar domainObjectDtos = _objectMapper.Map<List<BaseDomainDto>>(baseDomainObjects);\r\n\t\r\n\tdomainObjectDtos.Dump();\t\r\n}\r\n\r\nvoid Configure(IMapperConfiguration mapperConfiguration)\r\n{       \r\n   mapperConfiguration.CreateMap<BaseDomain, BaseDomainDto>()\r\n\t\t\t\t.Include<DomainA, DomainADto>()\r\n\t\t\t\t.Include<DomainB, DomainBDto>();\r\n\t\t\t\t\r\n\tmapperConfiguration.CreateMap<DomainA, DomainADto>();\r\n\tmapperConfiguration.CreateMap<DomainB, DomainBDto>();\r\n}\r\n\r\npublic abstract class BaseDomain\r\n{\r\n\tpublic int Id {get;set;}\r\n\tpublic string Text {get;set;}\r\n}\r\n\r\npublic class DomainA : BaseDomain\r\n{\r\n\tpublic string ExtraPropertyA {get;set;}\r\n}\r\n\r\npublic class DomainB : BaseDomain\r\n{\r\n\tpublic string ExtraPropertyB {get;set;}\r\n}\r\n\r\npublic abstract class BaseDomainDto\r\n{\r\n\tpublic int Id {get;set;}\r\n\tpublic string Text {get;set;}\r\n}\r\n\r\npublic class DomainADto : BaseDomainDto\r\n{\r\n\tpublic string ExtraPropertyA {get;set;}\r\n}\r\n\r\npublic class DomainBDto : BaseDomainDto\r\n{\r\n\tpublic string ExtraPropertyB {get;set;}\r\n}\r\n```\r\n\r\nScenario Two:- Doesn't work for abstract types however, works for non-abstract types\r\n\r\n```\r\nvoid Main()\r\n{\r\n\t\r\n\tIMapperConfiguration _mappingConfig = new MapperConfiguration(Configure);\r\n\t\t\r\n\t_mappingConfig.CreateMap<BaseDomain, BaseDomainDto>()\r\n\t\t\t\t.Include<DomainA, DomainADto>()\r\n\t\t\t\t.Include<DomainB, DomainBDto>();\r\n\t\t\t\t\r\n\t\t\t_mappingConfig.CreateMap<DomainA, DomainADto>();\r\n\t\t\t_mappingConfig.CreateMap<DomainB, DomainBDto>();\r\n\t \r\n\t \r\n\tIMapper _objectMapper = ((MapperConfiguration)_mappingConfig).CreateMapper();\r\n\t\r\n\tvar baseDomainObjects = new List<BaseDomain>\r\n\t{\r\n\t\tnew DomainA { Id = 1, Text = \"Domain A\", ExtraPropertyA = \"A\" },\r\n\t\tnew DomainB { Id = 2, Text = \"Domain B\", ExtraPropertyB = \"B\" }\r\n\t};\r\n\t\r\n\tvar domainAObjects = new List<DomainA>\r\n\t{\r\n\t\tnew DomainA { Id = 1, Text = \"A\", ExtraPropertyA = \"A\" },\r\n\t\tnew DomainA { Id = 2, Text = \"B\", ExtraPropertyA = \"B\" },\r\n\t\tnew DomainA { Id = 3, Text = \"C\", ExtraPropertyA = \"C\" },\r\n\t};\r\n\t\r\n\t\r\n\tvar domainObjectDtos = _objectMapper.Map<List<BaseDomainDto>>(baseDomainObjects);\r\n\t//var domainAObjectDtos = _objectMapper.Map<List<DomainADto>>(domainAObjects);\r\n\t\r\n\tdomainObjectDtos.Dump();\t\r\n\t//domainAObjectDtos.Dump();\r\n}\r\n\r\nvoid Configure(IMapperConfiguration mapperConfiguration)\r\n   {       \r\n   }\r\n\r\npublic abstract class BaseDomain\r\n{\r\n\tpublic int Id {get;set;}\r\n\tpublic string Text {get;set;}\r\n}\r\n\r\npublic class DomainA : BaseDomain\r\n{\r\n\tpublic string ExtraPropertyA {get;set;}\r\n}\r\n\r\npublic class DomainB : BaseDomain\r\n{\r\n\tpublic string ExtraPropertyB {get;set;}\r\n}\r\n\r\npublic abstract class BaseDomainDto\r\n{\r\n\tpublic int Id {get;set;}\r\n\tpublic string Text {get;set;}\r\n}\r\n\r\npublic class DomainADto : BaseDomainDto\r\n{\r\n\tpublic string ExtraPropertyA {get;set;}\r\n}\r\n\r\npublic class DomainBDto : BaseDomainDto\r\n{\r\n\tpublic string ExtraPropertyB {get;set;}\r\n}\r\n```\r\n"},"comment":{"url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/comments/221266740","html_url":"https://github.com/AutoMapper/AutoMapper/issues/1300#issuecomment-221266740","issue_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1300","id":221266740,"user":{"login":"jbogard","id":104498,"avatar_url":"https://avatars.githubusercontent.com/u/104498?v=3","gravatar_id":"","url":"https://api.github.com/users/jbogard","html_url":"https://github.com/jbogard","followers_url":"https://api.github.com/users/jbogard/followers","following_url":"https://api.github.com/users/jbogard/following{/other_user}","gists_url":"https://api.github.com/users/jbogard/gists{/gist_id}","starred_url":"https://api.github.com/users/jbogard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jbogard/subscriptions","organizations_url":"https://api.github.com/users/jbogard/orgs","repos_url":"https://api.github.com/users/jbogard/repos","events_url":"https://api.github.com/users/jbogard/events{/privacy}","received_events_url":"https://api.github.com/users/jbogard/received_events","type":"User","site_admin":false},"created_at":"2016-05-24T13:23:15Z","updated_at":"2016-05-24T13:23:15Z","body":"Hmmm, you're right, those two should be separated. I'll make sure they do before the 5.0 release.\r\n\r\nFor now, don't do that casting stuff. Initialize everything from the constructor."}}
{"actor":{"display_login":"jbogard"}}