使用C#将属性值复制到另一个对象


Copy the property values to another object with C#

本问题已经有最佳答案,请猛点这里访问。

要将属性值从一个对象复制到另一个对象,我们通常使用以下语法实现:

1
2
ca.pro1 = cb.pro2;
ca.pro2 = cb.pro2;

其中CA和CB属于同一类。

有没有更简单的synatx或效用方法来帮助我们达到同样的效果?

谢谢您。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void CopyPropertiesTo<T, TU>(this T source, TU dest)
{
    var sourceProps = typeof (T).GetProperties().Where(x => x.CanRead).ToList();
    var destProps = typeof(TU).GetProperties()
            .Where(x => x.CanWrite)
            .ToList();

    foreach (var sourceProp in sourceProps)
    {
        if (destProps.Any(x => x.Name == sourceProp.Name))
        {
            var p = destProps.First(x => x.Name == sourceProp.Name);
            if(p.CanWrite) { // check if the property can be set or no.
                p.SetValue(dest, sourceProp.GetValue(source, null), null);
            }
        }

    }

}


这是一个用于在ASP.NET MVC模型之间复制成员的函数。当您寻找一个适用于同一类型的代码时,此代码还将支持具有相同属性的其他类型。

它使用反射,但以更干净的方式。当心Convert.ChangeType:您可能不需要它;您可以检查类型而不是转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static TConvert ConvertTo<TConvert>(this object entity) where TConvert : new()
{
    var convertProperties = TypeDescriptor.GetProperties(typeof(TConvert)).Cast<PropertyDescriptor>();
    var entityProperties = TypeDescriptor.GetProperties(entity).Cast<PropertyDescriptor>();

    var convert = new TConvert();

    foreach (var entityProperty in entityProperties)
    {
        var property = entityProperty;
        var convertProperty = convertProperties.FirstOrDefault(prop => prop.Name == property.Name);
        if (convertProperty != null)
        {
            convertProperty.SetValue(convert, Convert.ChangeType(entityProperty.GetValue(entity), convertProperty.PropertyType));
        }
    }

    return convert;
}

因为这是一个扩展方法,所以使用起来很简单:

1
var result = original.ConvertTo<SomeOtherType>();


如果我没有错认为需要什么,那么在两个现有实例(甚至不是同一类型的实例)之间轻松实现属性值复制的方法就是使用automapper。

  • 创建映射配置
  • 然后调用.map(soure,target)
  • 只要将属性保持在相同的类型和命名约定中,所有属性都应该工作。

    例子:

    1
    2
    3
    4
    5
    6
    MapperConfiguration _configuration = new MapperConfiguration(cnf =>
                {
                    cnf.CreateMap<SourceType, TargetType>();
                });
    var mapper = new Mapper(_configuration);
    maper.DefaultContext.Mapper.Map(source, target)

    不是真的。有一个memberWiseClone(),但它直接复制引用,这意味着您将获得对同一对象的引用,这可能是错误的。您可以实现ICloneable接口,并将其用于深度复制。不过,我更喜欢使用自己的clone()方法,因为ICloneable接口返回一个需要强制转换的对象。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
       public static TTarget Convert<TSource, TTarget>(TSource sourceItem)
            {
                if (null == sourceItem)
                {
                    return default(TTarget);
                }

                var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace,  };

                var serializedObject = JsonConvert.SerializeObject(sourceItem, deserializeSettings);

                return JsonConvert.DeserializeObject<TTarget>(serializedObject);
            }

    用途:

    1
      promosion = YourClass.Convert<Promosion, PromosionExtension>(existsPromosion);