Skip to content

ArgumentException for expression parameter on UseAsDataSource().OrderBy with nullable type in destination #97

Closed
@mycroes

Description

@mycroes

When a DTO has a nullable property for a non-nullable source expression UseAsDataSource throws when trying to OrderBy on the destination property.

The following testcase reproduces this exception:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Shouldly;
using Xunit;

namespace AutoMapper.Extensions.ExpressionMapping.UnitTests
{
    public class MappingToNullablePropertyUsingUseAsDataSource
    {
        [Fact]
        public void When_Apply_OrderBy_Clause_Over_Queryable_As_Data_Source()
        {
            // Arrange
            var mapper = CreateMapper();

            var models = new List<Model>()
            {
                new Model {Value = 1},
                new Model {Value = 2}
            };

            var queryable = models.AsQueryable();

            Expression<Func<DTO, int?>> dtoPropertySelector = (dto) => dto.Value;

            // Act
            var result = queryable.UseAsDataSource(mapper).For<DTO>().OrderBy(dtoPropertySelector).ToList();

            // Assert
            result.ShouldNotBeNull();
            result.Count.ShouldBe(2);
        }

        private static IMapper CreateMapper()
        {
            var mapperConfig = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Model, DTO>();
            });

            var mapper = mapperConfig.CreateMapper();
            return mapper;
        }

        private class Model
        {
            public int Value { get; set; }
        }

        private class DTO
        {
            public int? Value { get; set; }
        }

    }
}

The error occurs in ExpressionMapper.GetConvertedMethodCall, where parameter dto => dto.Value of type Func<DTO, Nullable<int>> gets converted to Func<Model, int> and the generic type replacement doesn't cover the return type of the Func.

I tried to fix this myself, but I think this requires matching the converted arguments and their types against the generic arguments of the method, for which I couldn't think of a generic approach that wouldn't involve mapping for known types or method signatures only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions