0

I am using automapper to map expressions between classes that implement IEnumerable. The base classes look like this:

public abstract class EntityDtoBase<T> : DtoBase<T> where T : EntityDtoBase<T>
{
    public virtual int Id { get; set; }
} 

public abstract class PersistenceDtoBase<T> : DtoBase<T> where T : PersistenceDtoBase<T>
{
    public virtual int Id { get; set; }
}

public abstract class DtoBase<T> : IEnumerable<T> where T : DtoBase<T>
{
    private readonly IList<T> _items;

    public int Count => _items.Count;

    protected DtoBase()
    {
        this._items = new List<T>();
    }

    public void Add(T item)
    {
        _items.Add(item);
    }
    
    /* other methods like AddRange... */

    IEnumerator IEnumerable.GetEnumerator()
    {
        return _items.GetEnumerator();
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _items.GetEnumerator();
    }
}

After migrating to Automapper 10, expression mapping between classes enheriting from EntityDtoBase and PersistenceDtoBase throws a System.EntryPointNotFoundException : Entry point was not found. The configuration I am using in my project is similar to the one used in this unit test:

public class UserEntityDto : EntityDtoBase<UserEntityDto> { }
public class UserPersistenceDto : PersistenceDtoBase<UserPersistenceDto> { }

public class UserProfile : Profile
{
    public UserProfile() { CreateMap<UserEntityDto, UserPersistenceDto>().ReverseMap(); }
}

public class UnitTest
{
    private readonly IMapper _mapper;

    public UnitTest()
    {
        var sp = CreateServices();
        _mapper = sp.GetRequiredService<IMapper>();
    }

    private static IServiceProvider CreateServices()
    {
        return new ServiceCollection()
            .AddAutoMapper(cfg =>
            {
                cfg.AddExpressionMapping();
                cfg.AddCollectionMappers();
                cfg.ForAllMaps((map, exp) => exp.MaxDepth(1));
                cfg.AllowNullCollections = true;
                cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
            }, typeof(UnitTest).Assembly)
            .BuildServiceProvider(false);
    }

    [Fact]
    public void Should_Map_Expression()
    {
        Expression<Func<UserEntityDto, bool>> searchExpression = u => u.Id == 1;
        var searchExpressionMapped = _mapper.Map<Expression<Func<UserPersistenceDto, bool>>>(searchExpression);

        Assert.NotNull(searchExpressionMapped);
    }

You can find the complete unit test project here. The test succeeds using Automapper 9 and fails using Automapper 10.

jps
  • 20,041
  • 15
  • 75
  • 79
Mouad
  • 137
  • 1
  • 3
  • 11
  • 1
    It was not updated for 10, you'll have to wait. Unless you wanna do it yourself :) – Lucian Bargaoanu Jul 04 '20 at 11:53
  • @LucianBargaoanu Ahh ok. Should I report the issue on GitHub? – Mouad Jul 04 '20 at 12:22
  • 1
    No use, people are aware. – Lucian Bargaoanu Jul 04 '20 at 12:25
  • @LucianBargaoanu ok thanks. One last question please. In my project, when i replace IEnumerable by ICollection or IList in DtoBase declaration, AutoMapper gives me a StackOverflow exception. Knowing I have many dto's enheriting from EntityDtoBase and PersistenceDtoBase, somtimes containing collections of other dto's. Could you think of reason for that? – Mouad Jul 04 '20 at 12:43
  • A repro would help. Make a [gist](https://gist.github.com/lbargaoanu/9c7233441c3a3413cc2b9b9ebb5964a9) that we can execute and see fail. – Lucian Bargaoanu Jul 04 '20 at 12:48

0 Answers0