AutoMapper / AutoMapper.Extensions.ExpressionMapping

MIT License
143 stars 39 forks source link

Parameter not remapped when using a logical binary expression #126

Closed maboivin closed 3 years ago

maboivin commented 3 years ago

Suppose the following LINQPad program:

void Main()
{
    var mapper = new Mapper(new MapperConfiguration(config =>
    {
        config.CreateMap<Shape, ShapeDto>()
            .ForMember(dto => dto.ShapeType, o => o.MapFrom(s => s is Triangle ? ShapeType.Triangle : s is Circle ? ShapeType.Circle : ShapeType.Unknown))
            .ForMember(dto => dto.DynamicProperties, o => o.Ignore());

        //config.CreateMap<Triangle, ShapeDto>()
        //   .IncludeBase<Shape, ShapeDto>();
        //           
        //config.CreateMap<Circle, ShapeDto>()
        //    .IncludeBase<Shape, ShapeDto>();
    }));

    // Where clause where the parameter is not remapped.
    Expression<Func<ShapeDto, bool>> where = x => x.ShapeType == ShapeType.Circle;

    // Where clause where the parameter is remapped.
    //Expression<Func<ShapeDto, bool>> where = x => x.Name == "A";

    var whereMapped = mapper.MapExpression<Expression<Func<Shape, bool>>>(where).Dump();

    whereMapped.Compile()(new Circle()).Dump();
}

// Define other methods and classes here
public class Shape
{
    public string Name { get; set; }
}

public class Triangle : Shape
{
    public double A { get; set; }
    public double B { get; set; }
    public double C { get; set; }
}

public class Circle : Shape
{
    public double R { get; set; }
}

public enum ShapeType
{
    Unknown,
    Triangle,
    Circle,
}

public class ShapeDto
{
    public string Name { get; set; }
    public IDictionary<string, object> DynamicProperties { get; set; }
    public ShapeType ShapeType { get; set; }
}

When mapping the where expression x => x.ShapeType == ShapeType.Circle, it should map to x => (Convert(IIF((x Is Triangle), Triangle, IIF((x Is Circle), Circle, Unknown))) == 2) but instead, it maps to x => (Convert(IIF((s Is Triangle), Triangle, IIF((s Is Circle), Circle, Unknown))) == 2) where the parameter x is not remapped to parameter s.

It ultimately throws an InvalidOperationException with the message variable 's' of type 'UserQuery+Shape' referenced from scope '', but it is not defined.

Is there a configuration missing or could it be related to a specific case not handled in the XpressionMapperVisitor?

BlaiseD commented 3 years ago

Definitely an unhandled case. The fix would most likely be here.

maboivin commented 3 years ago

Hi @BlaiseD, I was able to test the scenario in a web app with version 4.1.2-alpha.0.7 and it solved the issue. Thanks for your quick response.

Now, could I ask you if there's any plan to release a new version?

Thanks again.

BlaiseD commented 3 years ago

@maboivin the master branch targets AutoMapper.vNext. For a release you may PR the 4.1.3 branch. with the changes from PR 127. 4.1.3 is just a copy of 4.1.2 - which targets Automapper v10.1.1 and can be released.

Make sense?

maboivin commented 3 years ago

@BlaiseD If I understood correctly, could you review https://github.com/AutoMapper/AutoMapper.Extensions.ExpressionMapping/pull/128?