将属性从对象复制到另一个对象的优雅方式

本文关键字:一个对象 方式 属性 对象 复制 | 更新日期: 2023-09-27 18:35:25

我有一个小型集成服务,它接收XML文件并对其进行解析。此外,我还从提供的 XSD 创建了用于反序列化 XML 数据的类。在解析过程中,我需要将属性从这些 XSD 生成的类复制到我在数据层中使用的我自己的类。这是我的一个例子

var supplierInfo = new SupplierInfo();
//coping properties
supplierInfo.Name = supplier.name;
supplierInfo.ShortName = supplier.shortName;
supplierInfo.BrandName = supplier.brandName;
supplierInfo.AdditionalFullName = supplier.additionalFullName;
supplierInfo.AdditionalCode = supplier.additionalCode;
supplierInfo.AdditionalInfo = supplier.additionalInfo;
//lot's of other properties
//...
supplierInfo.Tax = supplier.tax;
supplierInfo.RegistrationDate = supplier.registrationDate;

有时房产的面积非常大。是否有更合适的方法来复制这些属性?

将属性从对象复制到另一个对象的优雅方式

Automapper自古以来就已经存在了。久经考验。http://automapper.org/

下面是一个示例:

using System;
using AutoMapper;   
public class Program
{
    class SupplierInfo
    {
        public SupplierInfo( string name, string shortName, string brandName ) {
            Name = name; 
            ShortName = shortName; 
            BrandName = brandName;
        }
        public string Name {get; private set; }
        public string ShortName {get; private set; }
        public string BrandName {get; private set; }
    }
    class Supplier
    {
        public string name {get; set; }
        public string shortName {get; set; }
        public string brandName {get; set; }
    }       
    public static void Main()
    {
        var dto = new Supplier() {
            name = "Name 1",
            shortName = "Short Name 1",
            brandName = "Brand Name 1"
        };

        //From the tutorial:
        //You only need one MapperConfiguration instance typically per AppDomain and should be instantiated during startup.
        var config = new MapperConfiguration(cfg => cfg.CreateMap<Supplier, SupplierInfo>());
        var mapper = config.CreateMapper();
        SupplierInfo info = mapper.Map<SupplierInfo>(dto);
        Console.WriteLine( info.Name );
        Console.WriteLine( info.ShortName );
        Console.WriteLine( info.BrandName );
    }
}

官方入门指南可在以下位置找到 https://github.com/AutoMapper/AutoMapper/wiki/Getting-started

我很高兴对此

得到纠正,但我总是发现自动映射器(根据另一个答案),它按名称/约定映射属性值,在生产代码中使用有点吓人。

我真的没有一个像样的替代方案,但我更喜欢根据您的代码示例手动执行此操作 - 它更易于阅读和调试,如果您最终重命名类中的任何属性,很明显复制代码已损坏(或者如果您使用某些 IDE 工具重命名属性, 它会相应地更改复制代码)。

首先,安装 EntityLite.Core:

PM> Install-Package EntityLite.Core

然后使用它:

using inercya.EntityLite.Extensions;
...
supplierInfo.AssignPropertiesFrom(supplier);

EntityLite是我开发的微型ORM。它有一些小宝石:-)

编辑:

我猜您可能不想安装EntityLite.Core只是为了将某些属性从一个对象复制到另一个对象。因此,这里有使用反射AssignPropertiesFrom扩展方法的实现:

public static class ObjectExtensions
{
    public static void AssignPropertiesForm(this object target, object source)
    {
        if (target == null || source == null) throw new ArgumentNullException();
        var targetPropertiesDic = target.GetType().GetProperties().Where(p => p.CanWrite).ToDictionary(p => p.Name, StringComparer.CurrentCultureIgnoreCase);
        foreach (var sourceProp in source.GetType().GetProperties().Where(p => p.CanRead))
        {
            PropertyInfo targetProp;
            if (targetPropertiesDic.TryGetValue(sourceProp.Name, out targetProp))
            {
                targetProp.SetValue(target, sourceProp.GetValue(source, null), null);
            }
        }
    }
}

顺便说一下,这不是EntityLite实现。EntityLite 使用动态 IL 生成。