Click here to Skip to main content
15,883,869 members
Articles / Programming Languages / C#

Deep Copy Using AutoMapper

Rate me:
Please Sign up or sign in to vote.
2.31/5 (5 votes)
19 Jun 2016CPOL2 min read 26.2K   127   5   7
Deep copy an Object using AutoMapper. AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another

Introduction

I search through the web to find out Deep Copy of a complex object and found out three ways of doing it.

  1. Serialization
  2. Implementing ICloneable interface
  3. Using Reflection

As the Complex Object I was trying to clone was used by the entire team, I was not supposed to make any changes to it. 1 & 2 did not work for me. Did not wanted to go for reflection. Hence, I used Auto Mapper to Deep Copy an object.

Background

In the application, we had product information for eight languages. Some of the fields needed to be taken from English language and other fields had to be taken from respective product of international language. Hence, a class was written to map the translatable properties and create an international language product. Now when one by one we added the product to a Product List, it was replacing all the previous language products with the last product that we added. (Complex types are passed as reference). Hence, I used Automapper to achieve what was needed.

What is Automapper?

AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another. For more information, please visit this link.

Using the Code

Please add the nuget for AutoMapper in your application.

I had a complex class Product which is as below:

C#
using System;
using System.Collections.Generic;
 
namespace DeepCloneWithAutoMapper.Models
{
    [Serializable]
    public class Product
    {
        public bool IsAvailable { get; set; }
 
        public string Language { get; set; }
 
        public int ProductId { get; set; }
 
        public List<int> VariantIds { get; set; }
 
        public List<int> SiteIds { get; set; }
 
        public int MerretId { get; set; }
 
        public string Name { get; set; }
 
        public string CareDetails { get; set; }
 
        public string AdditionalCopy { get; set; }
 
        public string FabricConstruction { get; set; }
 
        public string Materials { get; set; }
 
        public string AdditionalInfo { get; set; }
 
        public string Description { get; set; }
 
        public int BrandId { get; set; }
 
        public string BrandName { get; set; }
 
        public string BrandDescription { get; set; }
 
        public string CareInfo { get; set; }
 
        public List<attribute> Attributes { get; set; }
 
        public string DateModified { get; set; }
 
        public string DateCreated { get; set; }
 
        public string BackOfficeDateModified { get; set; }
 
        public string ProductCode { get; set; }
 
        public int CategoryId { get; set; }
 
        public string Category { get; set; }
 
        public int DepartmentId { get; set; }
 
        public string Department { get; set; }
 
        public int DivisionId { get; set; }
 
        public string Division { get; set; }
 
        public int ShippingRestrictionId { get; set; }
 
        public bool IsReturnable { get; set; }
 
        public string TranslatableDataDateChanged { get; set; }
 
        public List<webcategory> WebCategories { get; set; }
 
        public List<associatedproductgroup> AssociatedProductGroups { get; set; }
 
        public int StatusId { get; set; }
    }
}

Though the Product class is Serializable but the Properties Like WebCategories and AssociatedProductGroups were not.

C#
public List WebCategories { get; set; }
public List AssociatedProductGroups { get; set; }

Please find the WebCategory and AssociatedProductGroup classes.

C#
//WebCategory
public class WebCategory
  {
    public int WebCategoryId { get; set; }

  }

// AssociatedProductGroup
public class AssociatedProductGroup
  {
    public int AssociatedProductGroupId { get; set; }
 
    public string Type { get; set; }
  }

I had a method "GetProductForAllLanguage". I wanted all languages products in a List by mapping the translatable properties. I was calling MapTranslatableProperties method to map the translatable properties and create a new product object and then add to a List. But this was replacing all the List products by the last product added. Hence, I used the AutoMapper for deep coping and creating a new object and then adding to the list.

public IEnumerable<Product> GetProductForAllLanguage()
        {
            var testProduct = new TestProduct();
            var productList = new List<Product>();
            productList.Add(testProduct.Product);
            productList.Add(testProduct.InternationalProduct);
            var internationalProduct = testProduct.InternationalProduct;
            internationalProduct.Language = "fr-Fr";
            productList.Add(internationalProduct);
 
            internationalProduct = testProduct.InternationalProduct;
            internationalProduct.Language = "ru-RU";
            productList.Add(internationalProduct);
 
            var feedProductsList = new List<Product>();
            var defaultLanguageProduct =
                productList.FirstOrDefault(p => p.Language == "en-GB");
 
            var otherLanguageProducts = productList.Where(s => s.Language != "en-GB");
            feedProductsList.Add(defaultLanguageProduct);
 
            // this is how we initialize automapper with the same object type. 
            Mapper.Initialize(cfg => { cfg.CreateMap<Product, Product>(); });
            foreach (var product in otherLanguageProducts)
            {
                
                var feedProduct = new Product();
                // map properties to give a new object. 
                feedProduct = Mapper.Map(defaultLanguageProduct, feedProduct);
                feedProduct = MapTranslatableProperties(feedProduct, product);
                feedProductsList.Add(feedProduct);
            }
 
            return feedProductsList;
        }

Points of Interest

I have wasted a huge amount of time searching on the web how to deep copy an object, but found only the above three methods. Just AutoMapper click to my mind and I tried the piece of code here. I played a small trick. Please share your view on this if this helps.

History

  • 17th June, 2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United Kingdom United Kingdom
Having 10 years of Experience in .net Web Technology.

Comments and Discussions

 
QuestionPerformance Pin
SledgeHammer0117-Jun-16 9:09
SledgeHammer0117-Jun-16 9:09 
AnswerRe: Performance Pin
Member 1218070719-Jun-16 20:44
Member 1218070719-Jun-16 20:44 
PraiseRe: Performance Pin
Member 1218070719-Jun-16 22:51
Member 1218070719-Jun-16 22:51 
GeneralRe: Performance Pin
SledgeHammer0120-Jun-16 8:31
SledgeHammer0120-Jun-16 8:31 
Yup . Now scale your test to 1M+!

Next gen object mappers all use EmitIL. Some of the more exotic use cases like mapping dictionary contents -- yikes -- AutoMapper can't even finish. EmitIL object mappers should be 1:1 with hand written C# if the the IL is built correctly and tuned -- so FastMapper is still kind of slow in that regard since it is taking 5x the handwritten C#.

I suspect he is not generating a static method or something like that. I wrote an EmitIL object mapper for the hell of it and its not as fully featured as AutoMapper (yet), but its 1:1 with the C# code since I built the IL from writing the code in C# and then disassembling it.
QuestionMapper.Initialize Pin
Member 1183537517-Jun-16 7:17
Member 1183537517-Jun-16 7:17 
AnswerRe: Mapper.Initialize Pin
lespauled17-Jun-16 8:08
lespauled17-Jun-16 8:08 
GeneralRe: Mapper.Initialize Pin
Member 1218070719-Jun-16 20:47
Member 1218070719-Jun-16 20:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.