AutoMapper/AutoMapper.Extensions.ExpressionMapping

Targeting multiple destination types in expression mapping

Opened this issue · 0 comments

Discussed in #174

Originally posted by kwaazaar January 17, 2024
When I want to map an expression on TSource to TTarget, it makes sense that my mapping configuration defines a map from TSource to TTarget. However, it also needs a map from TTarget to TSource. Why is that?

Also, mapping a certain expression, that worked on AM v6, now gives me this error, but I have no idea how to fix this: No generic method 'Count' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

        [Fact]
        public void CanMap()
        {
            var mapper = new AutoMapper.MapperConfiguration(cfg =>
            {
                cfg.CreateMap<SourceType, TargetType>().ReverseMap();
                cfg.CreateMap<SourceChildType, TargetChildType>().ReverseMap();

                // Same source type can map to different target types. This seems unsupported currently.
                cfg.CreateMap<SourceListItemType, TargetListItemType>().ReverseMap();
                cfg.CreateMap<SourceListItemType, TargetChildListItemType>().ReverseMap();

            }).CreateMapper();

            Expression<Func<SourceType, bool>> sourcesWithListItemsExpr = src => src.Id != 0 && src.ItemList != null && src.ItemList.Any(); // Sources with non-empty ItemList

            Expression<Func<TargetType, bool>> target1sWithListItemsExpr = mapper.MapExpression<Expression<Func<TargetType, bool>>>(sourcesWithListItemsExpr);
        }
        internal class SourceChildType
        {
            public int Id { get; set; }
            public IEnumerable<SourceListItemType> ItemList { get; set; } // Uses same type (SourceListItemType) for its itemlist as SourceType
        }

        internal class SourceType
        {
            public int Id { get; set; }
            public SourceChildType Child { set; get; }
            public IEnumerable<SourceListItemType> ItemList { get; set; }
        }

        internal class SourceListItemType
        {
            public int Id { get; set; }
        }

        internal class TargetChildType
        {
            public virtual int Id { get; set; }
            public virtual ICollection<TargetChildListItemType> ItemList { get; set; } = new List<TargetChildListItemType>();
        }

        internal class TargetChildListItemType
        {
            public virtual int Id { get; set; }
        }

        internal class TargetType
        {
            public virtual int Id { get; set; }

            public virtual TargetChildType Child { get; set; }

            public virtual ICollection<TargetListItemType> ItemList { get; set; } = new List<TargetListItemType>();
        }

        internal class TargetListItemType
        {
            public virtual int Id { get; set; }
        }