Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

Simplistic Object Copying in .NET


In many applications it’s necessary to copy data between objects. Especially these days where we often have entities and Data Transfer Objects (DTO) where data needs to be shuttled back and forth between two objects I find it handy to have a simple routine that performs at least rudimentary, shallow data copying for me without manually having to write data mapping code at least if the properties identically or nearly identically. A few days ago I had a lengthy discussion about this topic on Twitter as well and some suggestions that some sort of data copying mechanism should be built into the .NET framework.

Now there are a number of ways to ‘copy’ .NET objects. You can clone instances using the .Clone() method and there are various serialization/deserialization techniques that can be used. There’s also a very nice library called Automapper from Jimmy Bogard, that provides a declarative way to map/copy objects although you have to explicitly pre-declare your object types to be mapped the advantage of which is that most of the Reflection overhead is incurred only once. But this doesn’t always address the issue in a lot of application level scenarios. All these approaches create a new instance of an object rather than copying data into an existing instance. Also in a lot of situations I don’t actually want to copy two objects of the same type – take the Entity-> DTO object example: These two objects are of different types yet they have many (or often all) of the same properties that match 1-1 and need to be copied.

I’ve had a simple object copying routine in my base tool library for some years that performs shallow object copies by matching property/field names. It’s neither fancy nor very efficient as it uses Reflection, but it works well for many scenarios:

/// <summary>
/// Copies the data of one object to another. The target object 'pulls' properties of the first. 
/// This any matching properties are written to the target.
/// 
/// The object copy is a shallow copy only. Any nested types will be copied as 
/// whole values rather than individual property assignments (ie. via assignment)
/// </summary>
/// <param name="source">The source object to copy from</param>
/// <param name="target">The object to copy to</param>
/// <param name="excludedProperties">A comma delimited list of properties that should not be copied</param>
/// <param name="memberAccess">Reflection binding access</param>
public static void CopyObjectData(object source, object target, string excludedProperties, BindingFlags memberAccess)
{
    string[] excluded = null;
    if (!string.IsNullOrEmpty(excludedProperties))
        excluded = excludedProperties.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);

    MemberInfo[] miT = target.GetType().GetMembers(memberAccess);
    foreach (MemberInfo Field in miT)
    {
        string name = Field.Name;

        // Skip over any property exceptions
        if (!string.IsNullOrEmpty(excludedProperties) &&
            excluded.Contains(name))
            continue;

        if (Field.MemberType == MemberTypes.Field)
        {
            FieldInfo SourceField = source.GetType().GetField(name);
            if (SourceField == null)
                continue;

            object SourceValue = SourceField.GetValue(source);
            ((FieldInfo)Field).SetValue(target, SourceValue);
        }
        else if (Field.MemberType == MemberTypes.Property)
        {
            PropertyInfo piTarget = Field as PropertyInfo;
            PropertyInfo SourceField = source.GetType().GetProperty(name, memberAccess);
            if (SourceField == null)
                continue;

            if (piTarget.CanWrite && SourceField.CanRead)
            {
                object SourceValue = SourceField.GetValue(source, null);
                piTarget.SetValue(target, SourceValue, null);
            }
        }
    }
}

As you can see this is a pretty simplistic approach to copying – it uses Reflection to iterate over the target object and tries to read the properties on the source object. Matching property names are then read and assigned on the target object. If types don’t line up the routine will fail. You can explicitly give a list of properties that are to be excluded from updates. For entity updates this will usually be auto-generated fields like Pks and time stamps that should be skipped.

There are a few issues with this approach. The biggest is that it uses Reflection so it has a bit of overhead walking the two objects and and looking up fields. Using the most restrictive BindingFlags filter helps some but Reflection is relatively slow. Of course it depends on the scenario you are using this for. The other issue has to do with failure tracking – if property copies fail for whatever reason you may end up with an object that is in an invalid state as some properties may have already copied while others have not.

Copies are only shallow meaning only a single level is copied. Any nested objects are copied as full instances rather than walking through each individual child object (which gets very complicated quickly having to deal with object recursion, and various list types etc.).

I’ve had good luck with this routine in various applications, especially in service or callback scenarios where inbound parameter data has to be copied back to business entities. For example, here’s a REST API call in an ASP.NET MVC application that receives an XML or JSON raw post buffer that is deserialized and then inserted into the database:

[AcceptVerbs(HttpVerbs.Post | HttpVerbs.Put)]
public ActionResult PostNewCodeSnippetObject()
{
    StreamReader sr = new StreamReader(Request.InputStream);
    string data = sr.ReadToEnd();
    sr.Close();

    Snippet inputSnippet = null;

    if (Request.ContentType == "text/javascript" || Request.ContentType == "application/json")
    {
        JSONSerializer ser = new JSONSerializer(SupportedJsonParserTypes.WestWindJsonSerializer);
        inputSnippet = ser.Deserialize(data, typeof(Snippet)) as Snippet;
    }
    else if (Request.ContentType == "text/xml")
    {
        inputSnippet = SerializationUtils.DeSerializeObject(data, typeof(Snippet)) as Snippet;
    }
    else
        return ExceptionResult("Unsuppported data input format. Please provide input content-type as text/javascript, application/json or text/xml.");


    busCodeSnippet codeSnippet = new busCodeSnippet();
    codeSnippet.NewEntity();

    DataUtils.CopyObjectData(inputSnippet, codeSnippet.Entity, "Id", BindingFlags.Public | BindingFlags.Instance);

    if (!codeSnippet.Validate())
        return this.ExceptionResult("Code snippet validation failed: " + codeSnippet.ValidationErrors.ToString());

    if (!codeSnippet.Save())
        return this.ExceptionResult("Couldn't save new code snippet: " + codeSnippet.ValidationErrors.ToString());

    return ApiResult(codeSnippet.Entity);
}

In this case there are 15 properties copies and it sure beats writing out those 15 properties by hand and updating them as the structures change. Having a generic object copying routine reduces the amount of code as well as making maintenance easier as you don’t have to back fit object structure changes into the code.

Note that this example works with 2 objects of differing types: one is the input DTO, while the other is the business entity. Plain clone and serialization routines native in .NET don’t address this scenario because of the type differences. Automapper would potentially address this scenario but it can’t copy into an existing entity – here I need to have a new entity that generates a new PK and a couple of other defaults – creating a new instance wouldn’t be able to get those default values. This issue is more pronounced in some scenarios like LINQ to SQL Entities needing to be update.

Copying in the Runtime?

It would be nice if this sort of functionality was native to the .NET runtimes. This is such a common scenario IMHO, and I’ve seen tons of questions surrounding this topic (and one of them sparked the initial conversation again in Twitter last week). Internally the .NET framework could maybe get away with some direct property mapping for same types so there would be no need to reflect over fields/properties. For differing types Reflection (or as Automapper does – load based mapping) is probably unavoidable, but in many scenarios the performance reqiurements aren’t that critical since we’re usually talking about updates which tend to be much less frequent than reads in most applications. The other reason this should be in the runtime is that it’s a hideously complex process if done right (ie. deep copies) where you could specify object nesting levels and recursion behavior.

I’m not holding my breath. But I’d be interested if others are finding this functionality something they common use or wish they could use in a standard way.

Make Donation
Posted in .NET  CSharp  


Feedback for this Post

 
# re: Simplistic Object Copying in .NET
by Bob August 04, 2009 @ 8:59am
Or you could just use object.MemberwiseClone...
# re: Simplistic Object Copying in .NET
by alberto August 04, 2009 @ 9:07am
Automapper *maps* between different types too.
# re: Simplistic Object Copying in .NET
by Rick Strahl August 04, 2009 @ 9:26am
@Bob, Alberto - MemberwiseClone and Automapper still create new instances which is the biggest reason for the method.
# re: Simplistic Object Copying in .NET
by alberto August 04, 2009 @ 10:36am
From http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/02/11/automapper-0-2-released.aspx

Support for filling an existing object, instead of AutoMapper creating the destination object itself
# re: Simplistic Object Copying in .NET
by nappisite August 04, 2009 @ 3:40pm
This is mildly useful. I had to do something similiar years ago when working with a poorly designed webservice that had two nearly identical objects one for retrieving and one for updating so I had to map from one to the other and there were more than 700 properties. This approach assumes, and maybe its a justified assumption in a lot of scenarios, that properties will always have consistent names across the objects but it seems a little inelegant.
# re: Simplistic Object Copying in .NET
by James Newton-King August 04, 2009 @ 3:41pm
I recently used Automapper on a project for the first time and had a really good experience.
# re: Simplistic Object Copying in .NET
by Aman Tur August 04, 2009 @ 10:23pm
I had done this for my current project to map two ORM (SubSonic) objects for different tables with almost same number of properties.
# re: Simplistic Object Copying in .NET
by imperugo August 05, 2009 @ 1:53am
I use a custom library based on Reflection.Emit ad IL.
You can see the example here (italian language, but the code in c# :D):

http://imperugo.tostring.it/Blog/Post/DTO-IL-e-Reflection-nelle-nostre-applicazioni

The IL Code is in the end of post.
Is a simple example, but I think the it's very fast for create an instance and copy the values.

Byez
# re: Simplistic Object Copying in .NET
by Jose Silva August 05, 2009 @ 6:47am
Guys... How about a mapper class that just creates a map using expression trees? Compiling the logic just makes everything quite fast :) Lightning fast. Dynamic as reflection but brutally faster, with or without class instantiation (mapping two classes to one, for example).

Ps. If you want the code, just let me know ;)
# re: Simplistic Object Copying in .NET
by Jose Silva August 05, 2009 @ 7:35am
Dynamic = without the need of any configuration
# re: Simplistic Object Copying in .NET
by Rick Strahl August 05, 2009 @ 9:45am
@Josse - some time ago I played around with expression trees and dynamic code generation which worked and was fast once created, but the actual creation of the expression trees and compilation was thousands of times slower than even using reflection which IMHO negated any possible use of the technology. Not sure if this is the same thing you're referring to but here is that old post:

http://www.west-wind.com/weblog/posts/653034.aspx
# re: Simplistic Object Copying in .NET
by Joshua Go August 05, 2009 @ 12:52pm
Hi Rick,

Long time reader, first time commenting.

Anyway, I tend to do the same as you for copying between objects. Although I use the TypeDescriptor, PropertyDescriptorCollection, and PropertyDescriptor more often. Code wise everything else pretty is much the same. I'm sure underneath the covers TypeDescriptor.GetProperties() and obj.GetType().GetProperties() are the same, although the return types are different. I wonder if there are differences in speed??

One thing that I also do different is...I don't call GetProperty() in every iteration. Instead, before I enter my copy-loop I get the entire list of properties using TypeDescriptor.GetProperties(), which returns a collection and has a Find() function. Then at every iteration I just call myCollection.Find("PropertyName").

I find this very useful when I'm copying record(s) from a database. I'll usually name the database columns the same as the object properties, this way I can copy the record to an object in one function call.

- Josh
# re: Simplistic Object Copying in .NET
by Jose Silva August 06, 2009 @ 1:17am
@rick - I do remember your post. It was the kickstart for my test with expression trees. What I did was simple. Initially I inspect the source and destination classes with reflection to find the matching properties. I then build lambdas for getting the values from the source class and setting values on the destination class. I then build expression trees to sequence all the lambdas in order. After compiling everything (dynamically) I map one million instances in a flash.

Mapping (1:1):

ObjectMapper<SourceClass, DestinationClass> mapper = new ObjectMapper<SourceClass, DestinationClass>();

List<DestinationClass> output = new List<DestinationClass>();
foreach(SourceClass s in listOfSouceClasses)
{
DestinationClass destination = new DestinationClass();
mapper.Map(source, destination);
output.Add(destination);
}

Mapping (n:1):

ObjectMapper<SourceClass1, DestinationClass> mapper1 = new ObjectMapper<SourceClass1, DestinationClass>();
ObjectMapper<SourceClass1, DestinationClass> mapper2 = new ObjectMapper<SourceClass2, DestinationClass>();

DestinationClass destination = new DestinationClass();
mapper.Map(source, destination1);
mapper.Map(source, destination2);

As you can see this is easy and fast. I'm currently using the same concept to map a datareader and dataset to a class and avoid the complex mappings and error checking by hand. A lot of refactoring can be made, but all in good time. The ideia is good, I think.
# re: Simplistic Object Copying in .NET
by Jose Silva August 06, 2009 @ 1:19am
Sorry. One of the examples has errors (morning blindness :))

Mapping (n:1):

ObjectMapper<SourceClass1, DestinationClass> mapper1 = new ObjectMapper<SourceClass1, DestinationClass>();
ObjectMapper<SourceClass2, DestinationClass> mapper2 = new ObjectMapper<SourceClass2, DestinationClass>();

(...)

DestinationClass destination = new DestinationClass();
mapper1.Map(source1, destination);
mapper2.Map(source2, destination);
# re: Simplistic Object Copying in .NET
by Neslekkim August 19, 2009 @ 5:28am
You should also take a look at this automapper type project: http://glue.codeplex.com/
# links for 2009-08-19
by SKOROZSI.NET August 19, 2009 @ 2:04pm
links for 2009-08-19
# re: Simplistic Object Copying in .NET
by Rick Strahl August 29, 2009 @ 12:55pm
@Josh the main reason I use GetProperty/GetField is because I'm mixing and matching. Also I don't think it's going to make much of a difference in perf - the string lookups are a big part of the overhead and somewhere those type descriptors have to be instantiated anyway behind the scenes to do the invokation.

@Jose - but the process of up front mapping is slow and that was my point. You take that hit on start up. Once compiled and up and running perf is going to be very fast yes and maybe that's works out Ok.

I have to take a closer look but so far these copy operations are used only in a few places and since they are updates that don't occur in high volume perf isn't a super critical issue in this case. That may not always be the case but it is in this situation.
# re: Simplistic Object Copying in .NET
by David Sutherland September 02, 2009 @ 9:06am
There were some constuctive criticisms here but honestly I still liked the post. It's a simple and solution to a common problem.

Thanks;

Dave
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014