0

I created a domain entity and all set methods are private because they have some validations before setting the data.

So I have Dtos to exchange data and than I map it to the Entity so I could persist to the database if everything goes fine.

When mapping Dto to Entity I'm getting the Entity with all the properties filled but the SetXXX are not executed as it would happen if I called the constructor directly.

What is the best or correct approach for those cases when using AutoMapper?

Domain Entity

public Product(Guid id, ... decimal originalPrice, decimal discountedPrice...) :
            base(id)
        {
            OriginalPrice = CheckOriginalPrice(originalPrice, discountedPrice);
            DiscountedPrice = CheckDiscountedPrice(originalPrice, discountedPrice);
        }

        public virtual void SetOriginalPrice(decimal originalPrice, decimal discountedPrice)
        {
            OriginalPrice = CheckOriginalPrice(originalPrice, discountedPrice);
        }

private static decimal CheckOriginalPrice(decimal originalPrice, decimal discountedPrice)
        {
            if (originalPrice < 0)
                throw new ArgumentOutOfRangeException($"original price ({originalPrice} cannot be negative");
            else if (originalPrice < discountedPrice)
                throw new ArgumentOutOfRangeException($"original price ({originalPrice}) can not be lower than discounted price ({discountedPrice})!");

            return originalPrice;
        }

Map will succeed if I do this, so no validation is happening, how to trigger the constructor?

var product = _objectMapper.Map<CreateProductDto, Product>(product);

If I test the entity class directly it pass the test as the price is checked and I get the exception.

var exception = await Assert.ThrowsAsync<ArgumentOutOfRangeException>(async () =>
            {
                //Act
                var product =
                    new Product(
                        _guidGenerator.Create(),
                        ...
                        4.05m,
                        8.05m,
                        ...
                    );
            });
            //Assert
            exception.Message.ShouldContain("original price");

So, how can I achieve that when mapping using ObjetMapper.Map the constructor will get executed properly, is there an easy way to accomplish it?

Lucas
  • 35
  • 5
  • Does this answer your question? [Automapper - how to map to constructor parameters instead of property setters](https://stackoverflow.com/questions/2239143/automapper-how-to-map-to-constructor-parameters-instead-of-property-setters) – devNull Apr 22 '20 at 22:23

2 Answers2

2

AutoMapper has a feature called conditional mapping, which seems to be what you're looking for: https://docs.automapper.org/en/stable/Conditional-mapping.html

sunero4
  • 820
  • 9
  • 29
  • 1
    I actually managed to solve my problem by having a constructor with same parameters as my dto, that way AutoMapper can use the correct constructor directly. – Lucas Apr 22 '20 at 23:39
1

I actually managed to solve my problem by having a constructor with same parameters as my dto, that way AutoMapper can use the correct constructor directly.

Lucas
  • 35
  • 5