From 3bb5736facf1575a9ff0f111fac496c509c119c0 Mon Sep 17 00:00:00 2001 From: Blaise Taylor Date: Fri, 25 Nov 2022 09:09:49 -0500 Subject: [PATCH] Fixes Issue #152. EF.Property not mapped correctly. --- .../PrependParentNameVisitor.cs | 12 +++++ ...omChildReferenceWithoutMemberExpression.cs | 53 +++++++++++++++++++ ...MapParameterBodyWithoutMemberExpression.cs | 46 ++++++++++++++++ .../EF.cs | 12 +++++ 4 files changed, 123 insertions(+) create mode 100644 tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyFromChildReferenceWithoutMemberExpression.cs create mode 100644 tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyWithoutMemberExpression.cs create mode 100644 tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/EF.cs diff --git a/src/AutoMapper.Extensions.ExpressionMapping/PrependParentNameVisitor.cs b/src/AutoMapper.Extensions.ExpressionMapping/PrependParentNameVisitor.cs index ae40e80..7ffdfbc 100644 --- a/src/AutoMapper.Extensions.ExpressionMapping/PrependParentNameVisitor.cs +++ b/src/AutoMapper.Extensions.ExpressionMapping/PrependParentNameVisitor.cs @@ -18,6 +18,18 @@ public PrependParentNameVisitor(ParameterExpression currentParameter, string par public string ParentFullName { get; } public Expression NewParameter { get; } + protected override Expression VisitParameter(ParameterExpression node) + { + if (object.ReferenceEquals(CurrentParameter, node)) + { + return string.IsNullOrEmpty(ParentFullName) + ? NewParameter + : ExpressionHelpers.MemberAccesses(ParentFullName, NewParameter); + } + + return base.VisitParameter(node); + } + protected override Expression VisitTypeBinary(TypeBinaryExpression node) { if (!(node.Expression is ParameterExpression)) diff --git a/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyFromChildReferenceWithoutMemberExpression.cs b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyFromChildReferenceWithoutMemberExpression.cs new file mode 100644 index 0000000..ecda1f7 --- /dev/null +++ b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyFromChildReferenceWithoutMemberExpression.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace AutoMapper.Extensions.ExpressionMapping.UnitTests +{ + public class CanMapParameterBodyFromChildReferenceWithoutMemberExpression + { + [Fact] + public void Can_map_parameter_body_from_child_reference_without_member_expression() + { + // Arrange + var config = new MapperConfiguration(c => + { + c.CreateMap() + .ForMember(p => p.Brand, c => c.MapFrom(p => EF.Property(p, "BrandId"))); ; + + c.CreateMap() + .IncludeMembers(p => p.Category); + }); + + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + + var products = new List() { + new TestProduct { } + }.AsQueryable(); + + //Act + Expression> expr = x => x.Brand == 2; + var mappedExpression = mapper.MapExpression>>(expr); + + //Assert + Assert.Equal("x => (Convert(Property(x.Category, \"BrandId\"), Int32) == 2)", mappedExpression.ToString()); + } + + public class TestCategory + { + // Has FK BrandId + } + public class TestProduct + { + public TestCategory? Category { get; set; } + } + + public class TestProductDTO + { + public int Brand { get; set; } + } + } +} diff --git a/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyWithoutMemberExpression.cs b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyWithoutMemberExpression.cs new file mode 100644 index 0000000..e3c0f25 --- /dev/null +++ b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/CanMapParameterBodyWithoutMemberExpression.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace AutoMapper.Extensions.ExpressionMapping.UnitTests +{ + public class CanMapParameterBodyWithoutMemberExpression + { + [Fact] + public void Can_map_parameter_body_without_member_expression() + { + // Arrange + var config = new MapperConfiguration(c => + { + c.CreateMap() + .ForMember(p => p.Brand, c => c.MapFrom(p => EF.Property(p, "BrandId"))); + }); + + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + + var products = new List() { + new TestProduct { } + }.AsQueryable(); + + //Act + Expression> expr = x => x.Brand == 2; + var mappedExpression = mapper.MapExpression>>(expr); + + //Assert + Assert.Equal("x => (Convert(Property(x, \"BrandId\"), Int32) == 2)", mappedExpression.ToString()); + } + + public class TestProduct + { + // Empty, has shadow key named BrandId + } + + public class TestProductDTO + { + public int Brand { get; set; } + } + } +} diff --git a/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/EF.cs b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/EF.cs new file mode 100644 index 0000000..8587ba3 --- /dev/null +++ b/tests/AutoMapper.Extensions.ExpressionMapping.UnitTests/EF.cs @@ -0,0 +1,12 @@ +using System; + +namespace AutoMapper.Extensions.ExpressionMapping.UnitTests +{ + internal class EF + { + internal static object Property(object p, string v) + { + throw new NotImplementedException(); + } + } +}