Introduction
I search through the web to find out Deep Copy of a complex object and found out three ways of doing it.
- Serialization
- Implementing ICloneable interface
- 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:
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.
public List WebCategories { get; set; }
public List AssociatedProductGroups { get; set; }
Please find the WebCategory
and AssociatedProductGroup
classes.
public class WebCategory
{
public int WebCategoryId { get; set; }
}
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);
Mapper.Initialize(cfg => { cfg.CreateMap<Product, Product>(); });
foreach (var product in otherLanguageProducts)
{
var feedProduct = new Product();
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