65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 AutoMapper 进行深度复制

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.31/5 (5投票s)

2016年6月17日

CPOL

2分钟阅读

viewsIcon

27421

downloadIcon

150

使用 AutoMapper 深拷贝对象。AutoMapper 是一个简单的库,旨在解决一个看似复杂的问题——消除将一个对象映射到另一个对象所需的代码。

引言

我在网上搜索,想找到深拷贝复杂对象的方法,发现了三种方法:

  1. 序列化
  2. 实现 ICloneable 接口
  3. 使用反射

由于我尝试克隆的复杂对象被整个团队使用,我不能对其进行任何修改。方法 1 和 2 对我不起作用。我不想使用反射。因此,我使用 Auto Mapper 来进行深拷贝。

背景

在应用程序中,我们有八种语言的产品信息。有些字段需要从英语语言获取,而其他字段需要从各自国际语言的产品中获取。因此,编写了一个类来映射可翻译的属性并创建国际语言产品。现在,当我们逐个将产品添加到产品列表中时,它会用最后添加的产品替换所有以前的语言产品。(复杂类型按引用传递)。因此,我使用 Automapper 来实现所需的功能。

什么是 AutoMapper?

AutoMapper 是一个简单的库,旨在解决一个看似复杂的问题——消除将一个对象映射到另一个对象所需的代码。有关更多信息,请访问 此链接

Using the Code

请在您的应用程序中添加 AutoMapper 的 nuget 包。

我有一个复杂的类 Product,如下所示

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; }
    }
}

虽然 Product 类是 Serializable,但 WebCategoriesAssociatedProductGroups 属性不是。

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

请查找 WebCategoryAssociatedProductGroup 类。

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

  }

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

我有一个方法 "GetProductForAllLanguage"。我希望通过映射可翻译的属性,将所有语言的产品存储在一个列表中。我调用 MapTranslatableProperties 方法来映射可翻译的属性并创建一个新的产品对象,然后将其添加到 List 中。但是,这会将 List 中的所有产品替换为最后添加的产品。因此,我使用 AutoMapper 进行深拷贝并创建一个新对象,然后将其添加到列表中。

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;
        }

关注点

我浪费了大量时间在网上搜索如何深拷贝对象,但只找到了上述三种方法。AutoMapper 只是突然出现在我的脑海中,我尝试了这段代码。我耍了个小聪明。如果您觉得这有帮助,请分享您的看法。

历史

  • 2016 年 6 月 17 日:初始版本
© . All rights reserved.