Copy object properties: reflection or serialization - which is faster?
Asked Answered
C

5

13

I have two objects of the same type and need to copy property values from one object to another. There are two options:

  1. Use reflection, navigate through the properties of the first object and copy the values.

  2. Serialize the first object and deserialize a copy.

Both work for my requirement, the question is which do I better use in the terms of speed (cost)?

Example

class Person
{
    public int ID { get; set; }
    public string Firsthand { get; set; } 
    public string LastName { get; set; } 
    public int Age { get; set; } 
    public decimal Weight { get; set; } 
}

Need to copy property values from Person p1 to Person p2.

For this simple sample - which method is faster?

Update

For serialization I use the ObjectCopier suggested here: Deep cloning objects

For reflection I use this code:

foreach (PropertyInfo sourcePropertyInfo in copyFromObject.GetType().GetProperties())  
{
    PropertyInfo destPropertyInfo = copyToObject.GetType().GetProperty(sourcePropertyInfo.Name);

    destPropertyInfo.SetValue(
        copyToObject,
        sourcePropertyInfo.GetValue(copyFromObject, null),
        null);
}
Cyrillus answered 18/11, 2011 at 11:14 Comment(6)
How about autoMapper automapper.org or would just Clone() do the job?Presentment
Why can't yo do it with normal assignment?Personnel
@Miau, This seems to be a complex property copying system, thanks for the link, very interesting. But for my need currently I require it to be simple, so AutoMapper will be a canon for this case I think. But I will surely examine and use it for complex tasks.Cyrillus
@DavidKemp, since it must be a universal system which works for any supplied classes.Cyrillus
@Cyrillus so do you want a deep or shallow copy?Personnel
@DavidKemp, for my current task I need a shallow copy (just copy non-reference values).Cyrillus
V
14

It all depends on what you want to copy, and what kind of serializer you plan to use. Thing with serializers is, some of them might be actually using reflection as underlying mechanism of building objects.

Edit #1: As far as I know, BinaryFormatter used by your class does utilize reflection to do its work. So question is, can you write better (faster?) custom reflection code for your types than Microsoft did for general scenario?

Edit #2: Out of curiosity, I've run simple test. BinaryFormatter vs reflection in terms of performing shallow copy. Reflection code I used can be seen here:

var newPerson = Activator.CreateInstance<Person>();
var fields = newPerson.GetType().GetFields(BindingFlags.Public 
    | BindingFlags.Instance);
foreach (var field in fields)
{
    var value = field.GetValue(person);
    field.SetValue(newPerson, value);
}

What are the results compared to ObjectCopier class you're using? Reflection seems to perform 7 times faster than serialization code. This however applies to Person class with public fields. For properties, difference is still noticable, but it's only 2 times faster.

I assume difference comes from the fact that BinaryFormatter needs to use streams, which introduce additional overhead. Yet this is just my assumption, which might be far from facts.

Source code for testing program I used can be found here. Anybody is welcome to point flaws and possible problems with it :-)


Sidenote
As with all "I was wondering..." benchmarks, I suggest you take it with a grain of salt. Such optimizations should be only made when their performance actually becomes an issue.

Vanderbilt answered 18/11, 2011 at 11:32 Comment(4)
I have simple classes with primitive types, such as int, string, etc... I use serializer suggested here: https://mcmap.net/q/9283/-deep-cloning-objects Types of the classes are supplied by external code.Cyrillus
@net_prog: check my edit. I've run simple test for your class using both methods.Vanderbilt
Thank you, this is what I was looking for. I actually wanted the class to be with properties, not fields, I have corrected the sample. But even in this case reflection is faster as I can see.Cyrillus
If you specify System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.NonPublic as the search options for GetFields(), it includes backing fields for all properties.Acidophil
E
8

Ultimately, general-purpose serializers (such as BinaryFormatter, via ObjectCopier) are using reflection. How well they use it depends on the specific serializer, but there is always extra overhead involved if you are serializing.

Since you only want a shallow copy, a tool like AutoMapper is the most appropriate tool here; again, it is using reflection (but I expect it is doing it "the right way", i.e. not via GetValue()/SetValue()), but it doesn't have the serialization costs.

In this scenario, serialization is overkill; AutoMapper is perfectly reasonable. If you wanted deep-clones, it gets trickier... serialization may start being tempting. I still probably wouldn't choose BinaryFormatter myself, but I'm very fussy about serialization ;p

It would of course be trivial to right some basic reflection that does the same via GetValue() etc, but that would be slow. Another interesting option here is that you can use the Expression API to create an object copier at runtime.... but... AutoMapper does everything you'd need here, so it seems redundant effort.

Enright answered 18/11, 2011 at 11:42 Comment(0)
C
0

Binary serialization is very fast I use it a lot for this kind of problem

Deep cloning objects

Coincidentally answered 18/11, 2011 at 11:19 Comment(2)
For serialization I use the ObjectCopier from that thread, is it faster than reflection?Cyrillus
@Cyrillus how do you think BinaryFormatter (the serializer under ObjectCopier) gets its data? Hint: it starts with "r" and sounds like "deflection".Enright
D
0

If you are copying the properties during run time, reflection would be the answer. I would go for serialization if its not during run time. Serialization vs Reflection look at this once.

Datura answered 18/11, 2011 at 11:20 Comment(4)
If you know the properties of the object during run time, reflection would be waste of time, serialization would be the answer. But if you don't know the properties of the object during run time, reflection is the only solution i can think of.Datura
If you know the properties, why would serialization suddenly be better than reflection? Not sure that makes sense...Enright
because reflection is used when the type of object is not known during run time. If the type of object is already known, why to bother using reflection when serialization(binary serialization) is fast and easily achieved.Datura
That makes no sense at all. Serialisation is going to involve reflection here; adding the actual encode/decode steps only adds work. For two reasonable implementations of a reflection-copier vs serialisation, and for a shallow copy, the reflection-copier is preferable in every way. Spoken as someone who knows as awful lot about both reflection and serialisation.Enright
C
0
void Copy(object copyToObject, object copyFromObject)
{
    BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

    FieldInfo[] fields = copyFromObject.GetType().GetFields(flags);
    for (int i = 0; i < fields.Length; ++i)
    {
        BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
            | BindingFlags.Static;
        FieldInfo field = copyFromObject.GetType().GetField(fields[i].Name, bindFlags);
        FieldInfo toField = copyToObject.GetType().GetField(fields[i].Name, bindFlags);
        if(field != null)
        {
            toField.SetValue(copyToObject, field.GetValue(copyFromObject));
        }
    }
}
Capsize answered 10/8, 2017 at 5:41 Comment(1)
The code might answer the question. But you help the OP more if you explain what the code does and how it solves the question.Proudfoot

© 2022 - 2024 — McMap. All rights reserved.