Cowa
Cowa

Reputation: 113

Automapper - Mapping multiple properties from different classes to single one

I have 3 source classes

public class ProductModel
{
    public ProductModel(string modelNo)
    {
        ModelNo = modelNo;
        Styles = new List<ProductStyle>();
    }

    public string ModelNo { get; set; }
    public List<ProductStyle> Styles { get; set; }
}

public class ProductStyle
{
    public ProductStyle(string color)
    {
        Color = color;
        Variants = new List<ProductVariant>();
    }

    public string Color { get; set; }
    public List<ProductVariant> Variants { get; set; }

}

public class ProductVariant
{
    public ProductVariant(string size)
    {
        Size = size;
    }

    public string Size { get; set; }
}

public class Inventory //2021.10.13 11:30
{
    public string ModelNo { get; set; }
    public decimal Quantity { get; set; }
}

here is my target class

public class Product
{
    public string Code { get; set; }
    public List<ProductStock> {get;set;} //added new property
}

public class ProductStock //2021.10.13 11:30
{
    public decimal Quantity { get; set; }
}

Each model have styles, and each style have variants.

I have to map them in such a way that the result Code of Product contains above properties with the following naming convention

Code = String.Concat(ModelNo,"#",Color,"#",Size)

My mapper looks like this:

    public void Mapper()
    {
        foreach (var model in this.Data())
        {
            foreach (var style in model.Styles)
            {
                foreach (var variant in style.Variants)
                {
                    //our products are here
                    Product product = 
                                  _mapper.Map(model,
                                    _mapper.Map(style,
                                      _mapper.Map<ProductVariant, Product>(variant)));
                    products.Add(product);
                }
            }
        }
    }

Here is some data:

    public static void Data()
    {
        List<ProductModel> models = new List<ProductModel>();

        var variant1 = new ProductVariant("L");
        var variant2 = new ProductVariant("M");
        var variant3 = new ProductVariant("S");

        var style1 = new ProductStyle("BLUE");
        var style2 = new ProductStyle("RED"); ;

        style1.Variants.Add(variant1);
        style2.Variants.Add(variant2);
        style2.Variants.Add(variant3);

        var model1 = new ProductModel("model1");

        model1.Styles.Add(style1);
        model1.Styles.Add(style2);
    }

Please give me some advice what it should look like my constructor class to properly map multiple properties to one.

I tried like this, i overrides string Code each time, but this doesn't works.

public class TestProfile : Profile
{
    public TestProfile()
    {
        var model = CreateMap<ProductModel, Product>()
       .ForMember(o => o.Code, o => o.MapFrom(m => m.ModelNo));
       //.AfterMap((s, entity) =>
       // {
       //     entity.Code = String.Concat(entity.Code, "-", s.ModelNo);
       // });

        var style = CreateMap<ProductStyle, Product>()
        .AfterMap((v, entity) =>
        {
            entity.Code = String.Concat(entity.Code, "-", v.Color);
        });

        var variant = CreateMap<ProductVariant, Product>()
        .AfterMap((v, entity) =>
        {
            entity.Code = String.Concat(entity.Code, "-", v.Size);
        });

    }
}

Upvotes: 1

Views: 655

Answers (1)

Akshay G
Akshay G

Reputation: 2280

Use LINQ Expression in Custom Type Convertor.

Each ProductModel can be transformed to List<Product>. So you cannot create a mapping between ProductModel and Product.

Mapper Profile

CreateMap<List<ProductModel>, List<Product>>()
.ConvertUsing(p => p.SelectMany(m => m.Styles
                               .SelectMany(s => s.Variants
                                .Select(v => new Product() { Code = String.Concat(m.ModelNo, "#", s.Color, "#", v.Size) })))
                                 .ToList());

Code

.............
.............
models.Add(model1);
models.Add(model2);
var result = _mapper.Map<List<Product>>(models);

Upvotes: 1

Related Questions