1

I'm currently working out of a .NET 5 class library project with no Startup methods.

The idea behind what I'm, trying to achieve is that a developer can tap into this library and pass in an object. This object will run through the method, AutoMapper will grab the properties that align with the properties in the FirstDTO, then return a DTO that can be used throughout any other projects.

I'm relatively new to the AutoMapper bits and found this article here: How to configure Auto mapper in class library project?

I've liked this approach and have leveraged it to map a dynamic object to a DTO:

Configuration.cs

public static class Configuration
    {
        private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() =>
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
                cfg.AddProfile<MappingProfile>();
            });

            IMapper mapper = config.CreateMapper();

            return mapper;
        });

        public static IMapper Mapper => Lazy.Value;
    }

Almost verbatim approach.

I have my MappingProfile.cs class:

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<dynamic, FirstDTO>();
            CreateMap<dynamic, SecondDTO>();
        }
    }

When I call my base class I have the following method:

public class BaseLibraryClass : IBaseLibraryClass
    {
        public FirstDTO GetFirstObject(dynamic objectSentIn)
        {
            return Configuration.Mapper.Map<FirstDTO>(objectSentIn);
        }
    }

Which, in my though, should work.

Now when I write my xUnit unit tests, I'm having a failed Assert.Equal when comparing the FirstDTO with a built DTO:

        private readonly IBaseLibraryClass baseLibraryClass = new BaseLibraryClass();
        private readonly FirstDTOBuilder firstDTOBuilder = new FirstDTOBuilder();

        [Fact]
        public void TestSeparateObject()
        {
            // Arrange
            FirstDTO firstDTO = firstDTOBuilder.DefaultDTO().Build();

            // Act
            FirstDTO result = baseLibraryClass.GetFirstObject(firstDTO);

            // Assert
            Assert.Equal(firstDTO, result);
        }

What ends up happening when I debug this unit test, is that a DTO is built with the assigned properties via the Builder. It passes the DTO into GetFirstObject successfully with the populated properties, but when it hits the return, it returns a FirstDTO object type with properties that are all zeroed out, ultimately failing my unit test.

I feel like it's something glaringly obvious, but I cannot for the life of me figure out what's causing the properties to not map properly.

Any assistance would be greatly appreciated!

Chobo
  • 76
  • 8
  • 1
    Hint - what would be actual type for first generic type parameter for `CreateMap` ? – Guru Stron Dec 01 '21 at 15:08
  • Ah! Thank you for this! Since the object is unknown, I've tossed in a Dictionary to map to the DTO. That way the properties will effectively map from any type that gets passed in there. Thank you so much! Please feel free to leave an answer and I'll mark it as the correct one :) – Chobo Dec 01 '21 at 15:16

1 Answers1

2

Automapper supports mapping from dynamic out of the box, no need to configure anything, so in your case removing profile from the configuration (or removing CreateMap's from the profile) should just work:

public static class Configuration
{
    private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() =>
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
        });

        IMapper mapper = config.CreateMapper();

        return mapper;
    });

    public static IMapper Mapper => Lazy.Value;
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Ahh! This is even better than what I thought to fix with the ```Dictionary``` fix. Thank you! I would upvote, but I don't have enough reputation, but this is definitely the answer! – Chobo Dec 01 '21 at 15:24
  • 1
    Got enough reputation to come back and upvote this. Thanks again for your help! – Chobo Dec 15 '21 at 13:58
  • 1
    @Chobo was glad to help! – Guru Stron Dec 15 '21 at 14:13