40

To copy the property values from one object to another, we usually achieve with following syntax:

ca.pro1 = cb.pro1; // same prop of different instances
ca.pro2 = cb.pro2;

where ca and cb are of the same class.

Is there any simpler syntax or utility method to help us to achieve the same effect?

Thank you.

2
  • This is what you're looking for: Cloning objects in C# Commented Aug 10, 2010 at 3:21
  • 2
    Cloning is not the same as copying in the context of this question: The OP doesn't say it is okay to instantiate an object. The answers provided here are useful and distinct from the answers found under "cloning" questions. Commented Sep 14, 2021 at 3:02

5 Answers 5

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

    }

}
Sign up to request clarification or add additional context in comments.

2 Comments

Why if(p.CanWrite)? destProps are already of CanWrite type.
You can optimize like this : var p = destProps.FirstOrDefault(x => x.Name == sourceProp.Name); if (p != null) p.SetValue(dest, sourceProp.GetValue(source, null), null);
15

If I am not mistaken with what is required, the way to easily achieve property value copy between two existing instances (even not of the same type) is to use Automapper.

  1. create mapping configuration
  2. and then call .Map(soure, target)

As long as you keep property in same type and in same naming convention, all should work.

Example:

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

Comments

12

This is a function that I used to copy members between models in ASP.NET MVC. While you seek a code that work for the same type, this code will also support other types that has the same properties.

It uses reflections, but in a more clean manner. Beware of the Convert.ChangeType: you might not need it; you could do a check on the type instead of converting.

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

Since this is an extension method, the usage is simple:

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

4 Comments

PropertyDescriptor.SetValue didn't work for me, had to use var convertProperties = typeof(TConvert).GetProperties(); - which gives you a List of PropertyInfo instead of PropertyDescriptor's
In Hindsight: "didn't work" meaning, the code ran, but it did not set any values, for example bool properties, b/c they had private setters (D'oh!).
This didnt work for me either, getting Invalid cast from 'System.Int32' to 'System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
@Jean-Paul It seem to fail when using nullable type. I invite you to find a solution and update this post. Or you should seek an existing library like Automapper.
2

not really. there is a MemberwiseClone() but that copies references directly meaning you would get a reference to the same object and that can be bad. You can implement the ICloneable interface and use that for a deep copy. I prefer making my own Clone() method though because the ICloneable interface returns an Object that needs to be cast.

4 Comments

I wouldn't bother with ICloneable, it is impossible to properly implement it because the interface doesn't allow the caller to indicate what he means by "clone".
i believe the de facto standard is a deep clone, but that also goes with what i said about making your own clone method, for better type safety, etc.
MemberwiseClone is not applicable to this question. It always creates a new object; this question is about updating fields in an existing object, from another object.
According to the Help, MemberwiseClone copies fields -- not properties.
1
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);
}

usage:

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.