{"action":"created","issue":{"url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1295","repository_url":"https://api.github.com/repos/AutoMapper/AutoMapper","labels_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1295/labels{/name}","comments_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1295/comments","events_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1295/events","html_url":"https://github.com/AutoMapper/AutoMapper/issues/1295","id":156104079,"number":1295,"title":"Incorrect mapping in case of multiple interfaces","user":{"login":"avgur","id":400951,"avatar_url":"https://avatars.githubusercontent.com/u/400951?v=3","gravatar_id":"","url":"https://api.github.com/users/avgur","html_url":"https://github.com/avgur","followers_url":"https://api.github.com/users/avgur/followers","following_url":"https://api.github.com/users/avgur/following{/other_user}","gists_url":"https://api.github.com/users/avgur/gists{/gist_id}","starred_url":"https://api.github.com/users/avgur/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/avgur/subscriptions","organizations_url":"https://api.github.com/users/avgur/orgs","repos_url":"https://api.github.com/users/avgur/repos","events_url":"https://api.github.com/users/avgur/events{/privacy}","received_events_url":"https://api.github.com/users/avgur/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":12,"created_at":"2016-05-21T14:16:36Z","updated_at":"2016-05-25T20:47:08Z","closed_at":null,"body":"Automapper version 4.2.1\r\nIn case when source implements more than one interface and we do not have mapping configuration for the source but have it for interfaces it will be impossible to use mapping configured for second (third, fourth...) interface\r\n\r\n```\r\n        public interface IChildA\r\n        {\r\n            string PropertyA { get; set; }\r\n        }\r\n\r\n        public interface IChildB\r\n        {\r\n            string PropertyB { get; set; }\r\n        }\r\n\r\n        public class Source : IChildA, IChildB\r\n        {\r\n            public string PropertyA { get; set; }\r\n\r\n            public string PropertyB { get; set; }\r\n        }\r\n\r\n        public class Destination\r\n        {\r\n            public string PropertyA { get; set; }\r\n\r\n            public string PropertyB { get; set; }\r\n        }\r\n...\r\n\r\n        public void MappingTest()\r\n        {\r\n            var conf = new MapperConfiguration(\r\n                config =>\r\n                {\r\n                    config.CreateMap<IChildA, Destination>();\r\n                    config.CreateMap<IChildB, Destination>();\r\n                });\r\n            var mapper = conf.CreateMapper();\r\n\r\n            var src = new Source { PropertyA = \"A\", PropertyB = \"B\" };\r\n            var dest = new Destination();\r\n            mapper.Map<IChildA, Destination>(src, dest); // will map PropertyA\r\n            mapper.Map<IChildB, Destination>(src, dest); // will NOT map PropertyB\r\n\r\n            Trace.WriteLine(dest.PropertyA == src.PropertyA); // true\r\n            Trace.WriteLine(dest.PropertyB == src.PropertyB); // false !!!\r\n        }\r\n\r\n```\r\n\r\nThe code above will not fill PropertyB (It will in case we will change order of interfaces in the Source class declaration)\r\n\r\nThe reason is MapperConfiguration.ResolveTypeMap method:\r\n\r\n```\r\n        public TypeMap ResolveTypeMap(object source, object destination, Type sourceType, Type destinationType)\r\n        {\r\n            return ResolveTypeMap(source?.GetType() ?? sourceType, destination?.GetType() ?? destinationType);\r\n        }\r\n\r\n```\r\n\r\nIt will call source.GetType() and then will look for the first known mapping (it will be IChildA in our case), so  \"sourceType\" (IChildB in our case) will be ignored and we will got invalid mapping."},"comment":{"url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/comments/221702330","html_url":"https://github.com/AutoMapper/AutoMapper/issues/1295#issuecomment-221702330","issue_url":"https://api.github.com/repos/AutoMapper/AutoMapper/issues/1295","id":221702330,"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-25T20:47:08Z","updated_at":"2016-05-25T20:47:08Z","body":"Man, this is ugly to try and handle both scenarios. Changing the rules to fit the above scenario make about a dozen other tests fail. This one is a good example:\r\n\r\n```\r\npublic class Container\r\n{\r\n    public BaseA Item { get; set; }\r\n}\r\n\r\npublic class Container2\r\n{\r\n    public BaseB Item { get; set; }\r\n}\r\npublic class BaseA\r\n{\r\n    public string Name { get; set; }\r\n}\r\n\r\npublic class BaseB\r\n{\r\n    public string Name { get; set; }\r\n}\r\n\r\npublic class ProxyOfSubA : SubA\r\n{\r\n}\r\npublic class SubA : BaseA\r\n{\r\n    public string Description { get; set; }\r\n}\r\n\r\npublic class SubB : BaseB\r\n{\r\n    public string Description { get; set; }\r\n}\r\n\r\n            var config = new MapperConfiguration(cfg =>\r\n            {\r\n                cfg.CreateMap<BaseA, BaseB>().Include<SubA, SubB>();\r\n                cfg.CreateMap<SubA, SubB>();\r\n                cfg.CreateMap<Container, Container2>();\r\n            });\r\n\r\n            var mapped = config.CreateMapper().Map<Container, Container2>(new Container() { Item = new ProxyOfSubA() { Name = \"Martin\", Description = \"Hello\" } });\r\n            Assert.IsType<SubB>(mapped.Item);\r\n```\r\n\r\nAutoMapper sees properties of BaseA -> BaseB. But the runtime value is a subtype of SubA, ProxyOfSubA. The runtime mapping is ProxyOfSubA -> BaseB, but we want to pick SubA -> SubB mapping. Instead, BaseB is chosen.\r\n\r\nBasically, I can't get both behaviors to work without doing some multiple matching and doing a ranking. And that makes my head hurt."}}
{"actor":{"display_login":"jbogard"}}