Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper: Auto map collection property for a dto object

Tags:

automapper

I have a domain object

public class ProductModel
{
    public long Id {get;set;}
    public string Name {get;set;}
    public string SerialNumber {get;set;}
}

Single Dto class:

public class ProductDto
{
    public long Id {get;set;}
    public string Name {get;set;}
    public string SerialNumber {get;set;}
}

Single Dto class that is a list of Dto object:

public class ProductListDto : List<ProductDto>
{
    public List<ProductDto> Products;

    public ProductListDto()
    {
        Products = new List<ProductDto>();
    }
}

And I'd like to map a list of domain objects to list of Dto objects such that the "Products" property of ProductListDto object AUTOMATICALLY is mapped with a list of ProductModel objects:

ProductListDto dto = new ProductListDto();  

Mapper.CreateMap<ProductModel, ProductDto>();

/* dto = (ProductListDto) Mapper.Map<List<ProductModel>, List<ProductDto>>((List<ProductModel>)model);  this code line causes error. It is commented out. */ 

dto.Products = Mapper.Map<List<ProductModel>, List<ProductDto>>((List<ProductModel>)model);  // (*)  works OK but need to specify "Products" property

The code line (*) works OK, but I'd like to know if there is another way to AUTOMATICALLY (implicitly) map that "Products" property of dto object other than the code line (*)?

That means I do not have to write code like the left hand side of code line (*).

like image 573
user1219702 Avatar asked Nov 20 '12 17:11

user1219702


People also ask

How do I use AutoMapper to list a map?

How do I use AutoMapper? First, you need both a source and destination type to work with. The destination type's design can be influenced by the layer in which it lives, but AutoMapper works best as long as the names of the members match up to the source type's members.

Does AutoMapper map private properties?

AutoMapper will map property with private setter with no problem. If you want to force encapsulation, you need to use IgnoreAllPropertiesWithAnInaccessibleSetter. With this option, all private properties (and other inaccessible) will be ignored.

Can AutoMapper map enums?

The built-in enum mapper is not configurable, it can only be replaced. Alternatively, AutoMapper supports convention based mapping of enum values in a separate package AutoMapper.

How does AutoMapper work in C#?

AutoMapper in C# is a library used to map data from one object to another. It acts as a mapper between two objects and transforms one object type into another. It converts the input object of one type to the output object of another type until the latter type follows or maintains the conventions of AutoMapper.


1 Answers

You will need to create a mapping for it. Something like this should work:

namespace StackOverflow
{
    using System.Collections.Generic;

    using AutoMapper;

    public class MyProfile : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "MyProfile";
            }
        }

        protected override void Configure()
        {
            Mapper.CreateMap<ProductModel, ProductDto>();

            Mapper.CreateMap<List<ProductModel>, ProductListDto>()
                .ForMember(dest => dest.Products,
                           opt => opt.MapFrom(
                               src => Mapper.Map<List<ProductModel>,
                                                 List<ProductDto>>(src)));
        }
    }
}

Then in your code you can do:

dto = Mapper.Map<List<ProductModel>, ProductListDto>((List<ProductModel>)model);

Here are a couple of unit tests to show how it works:

namespace StackOverflow
{
    using System.Collections.Generic;

    using AutoMapper;

    using NUnit.Framework;

    [TestFixture]
    public class MappingTests
    {
        [Test]
        public void AutoMapper_Configuration_IsValid()
        {
            Mapper.Initialize(m => m.AddProfile<MyProfile>());
            Mapper.AssertConfigurationIsValid();
        }

        [Test]
        public void AutoMapper_DriverMapping_IsValid()
        {
            Mapper.Initialize(m => m.AddProfile<MyProfile>());
            Mapper.AssertConfigurationIsValid();

            var products = new List<ProductModel>
                {
                    new ProductModel
                        {
                            Id = 1,
                            Name = "StackOverflow Rocks",
                            SerialNumber = "1234"
                        },
                    new ProductModel
                        {
                            Id = 2,
                            Name = "I Also Rock",
                            SerialNumber = "4321"
                        }
                };

            var productsDto =
                    Mapper.Map<List<ProductModel>, ProductListDto>(products);

            Assert.That(productsDto, Is.Not.Null);
            Assert.That(productsDto.Products, Is.Not.Null);
            Assert.That(productsDto.Products.Count, Is.EqualTo(2));
        }
    }
}
like image 50
Mightymuke Avatar answered Nov 15 '22 11:11

Mightymuke