95

I have a class:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

I have two instances of Person (person1 and person2). I'd like copy the contents of person2 to person1. I'd like to make this copy in one instruction and not property by property:

person1.LastName = person2.LastName;

In the doc, I see copy an object to another object but the type is different. How can I copy the object when the type is the same ?

Boann
  • 48,794
  • 16
  • 117
  • 146
TheBoubou
  • 19,487
  • 54
  • 148
  • 236
  • 17
    @Darin - That would create a reference, not a copy. – Steven Ryssaert Apr 19 '11 at 09:02
  • 1
    @Uw Concept, yes, but as the question is not very clear I thought I might suggest this. – Darin Dimitrov Apr 19 '11 at 09:04
  • 3
    Don't want create a reference but a copy completely independant – TheBoubou Apr 19 '11 at 09:40
  • 6
    I suggest not using AutoMapper for this - it's not designed to clone items (though it might work in some scenarios). Instead, that BinaryFormatter trick works magic, and is easily encapsulated in an extension method. – Jimmy Bogard Apr 19 '11 at 12:36
  • @JimmyBogard why would not? Is it merely a feature not implemented in automapper, or is there something in cloning that *conceptually* goes against mapping? Conceptually they are the same operations, no? So the logic could be simply extended to cloning as well right, in fact more easily? – nawfal Jul 22 '14 at 21:24
  • 4
    Conceptually, no, they are not the same operations. Cloning also concerns private, not just public data. Cloning basically ONLY looks at private fields, whereas mapping does not. – Jimmy Bogard Jul 23 '14 at 15:29

5 Answers5

97

As I understand the question, OP does not want to clone person2 into a new instance of Person, but is asking for how to copy the contents of person2 into an already existing instance (person1) of Person. There is an overload of AutoMapper's Mapper.Map method that does this for you:

Mapper.CreateMap<Person, Person>();
Mapper.Map<Person, Person>(person2, person1);
//This copies member content from person2 into the _existing_ person1 instance.

Note 1: @alexl's answer creates a new instance of Person. If you have other references to the instance that person1 points to, these will not get the (presumably) desired data update if you redirect the person1 variable to a new instance.

Note 2: You need to be aware of that the (recursive) copying depth depends on what mappings AutoMapper knows about at the moment of mapping!
If a member of the Person class is of say the class Brain and you additionally have done Mapper.CreateMap<Brain, Brain>(); before the copy data Mapper.Map<Person, Person>(person2, person1); call, then person1 will keep its current Brain instance but this Brain will receive the member values of person2's Brain instance. That is you have a deep copy.
But if AutoMapper does not have a Brain-Brain mapping before copying, then person1's Brain member will reference the same Brain instance as the one person2 references. That is you will get a shallow copy.
This applies recursively to all members, so you better make sure AutoMapper has mappings for member classes that you want to deep copy, and doesn't have mappings for member classes that you want to shallow copy.

An alternative to using AutoMapper would be to use an approach using reflection. (Note that the code in the link does a shallow copy!)

"Support for filling an existing object, instead of AutoMapper creating the destination object itself" was added in AutoMapper version 0.2.

Ulf Åkerstedt
  • 3,086
  • 4
  • 26
  • 28
  • 1
    this seems to work on object level, but other objects as properties are copied by reference. maybe there is a way to tell automapper to clone the properties instead of copying a ref? – Sonic Soul Dec 07 '17 at 19:39
37

Since you asked With Automapper? can I suggest you don't use AutoMapper?

Instead use MemberwiseClone() in a Clone method, e.g.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person Clone()
    {
        return (Person) MemberwiseClone();
    }
}

UPDATE

Its important to note this does not acheive the original posters desire to copy person1 into person2

However, (and as @Jimmy Bogard points out) using MemberwiseClone() is preferred if you just need to make a copy (clone) of the object.

For instance, if you are doing this:

//I need a copy of person1 please! I'll make a new person object 
//and automapper everything into it!
var person2 = new Person2();
Mapper.Map<Person, Person>(person1, person2)

then really you should/could use

//oh wait, i can just use this!
var person2 = person1.Clone()
Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
wal
  • 17,409
  • 8
  • 74
  • 109
  • 5
    The only problem with this is you are now stating that your Person type can be cloned. This is semantically incorrect, the goal is to perform a copy (not a clone) from one instance into another instance. – Shaun Wilson Jan 23 '13 at 19:39
  • can you please elaborate on the differences with regard to this specific example ? – wal Jan 23 '13 at 22:49
  • 6
    wal: MemberwiseClone creates a _new_ instance of Person. OP wants to _keep the already existing_ instance that Person1 points to and fill it with the values of Person2. There might be other references to the instance that Person1 points to that will not get the desired data update if you redirect the Person1 to a new instance. – Ulf Åkerstedt Feb 28 '13 at 11:11
  • @UlfÅkerstedt ok fair point however I think its important to remember not all questions/answers can be black and white. Its important to establish what the OP (and others who come across this post) are trying to acheive. I will update my answer accordingly to clarify. – wal Feb 28 '13 at 12:35
  • 9
    object.MemberwiseClone() performs a shallow copy, NOT deep copy by the way. https://www.google.ch/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=shallow%20copy%20vs%20deep%20copy – Errore Fatale Oct 09 '15 at 15:13
  • 2
    You did not explain why NOT using AutoMapper? Is I'm the one here who think that `return (Person) MemberwiseClone();` is a bad practice or simply a "code smell"? – Geka P Jan 09 '17 at 18:15
  • @GekaP the OP indicates (in his comments) that he wants to make a copy of the object. `MemberwiseClone()` is not bad practice – wal Jan 09 '17 at 22:48
  • The last two examples are not equivalent. AutoMapper creates a deep clone/copy of the data, including for nested reference types, it does not simply do assignment copy which copies the same object references. Clone() and ICloneable() does not guarantee what kind of clone it does (shallow/deep). – Paul-Sebastian Manole Sep 24 '21 at 20:52
23
Mapper.CreateMap<Person, Person>();

// Perform mapping

var person1 = Mapper.Map<Person, Person>(person2);

Hope this helps.

alexl
  • 6,841
  • 3
  • 24
  • 29
  • 18
    Shouldn't this be `Mapper.Map(person2, person1);` ? Your way will create a new object `person1` (which i'm being slayed for in my answer ;) ) – wal Feb 28 '13 at 12:45
  • 4
    For people who google in here: Map.CreateMap was removed and the new way to configure mapping is described here https://stackoverflow.com/a/38194308/4547594 – Igand May 10 '18 at 13:47
  • Does Automapper only copy simple properties or it copies extra navigation properties as well? How can I tell it to only copy the simple properties and not object properties? – Naomi Jul 13 '18 at 22:24
  • I'm finding if Person is a nested property mapped from another mapping, then it will just copy the same instance rather than map to a new instance. – Josh Sutterfield Nov 09 '21 at 21:29
8

In the current version of AutoMapper, you can't use the static AutoMapper.Mapper.Map method. Instead, initialize a new mapper like this:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Person, Person>();
});

var mapper = new Mapper(config);

var clone = mapper.Map<Person>(person);

Usually, you want to register the mapper in the Startup.cs file for dependency injection and inject it in your business class:

public void ConfigureServices(IServiceCollection services)
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Person, Person>();
    });

    var mapper = new Mapper(config);

    services.AddSingleton(mapper);

    // ...
}

Important: Don't create or inject the mapper in your entity class!

Of course, you should prefer to use MemberwiseClone() in simple cases.

MovGP0
  • 7,267
  • 3
  • 49
  • 42
1

Why do you want to use Automapper for this? A simple clone would do the job for you.

Read more here: Deep cloning objects

Community
  • 1
  • 1
boena
  • 187
  • 1
  • 7
  • 7
    Because AutoMapper uses reflection which is faster than binary serialization. – huysentruitw Sep 26 '14 at 12:43
  • 4
    And AutoMapper does not require all types involved to be marked [Serializable]. AutoMapper is also configurable; if you want to only copy some of the fields, or do some sort of transformation as part of the copy, it can do that. :-) – Jonathan Gilbert Jun 15 '16 at 21:38
  • 12
    A "simple" deep clone? We have different definitions of simple. – Gusdor Nov 02 '16 at 14:31
  • 3
    @WouterHuysentruit Automapper also allows you to unit testing the mapping. Brilliant if you amend the type later in life. – Gusdor Nov 02 '16 at 14:32
  • Because AutoMapper may be used for other reasons on a different level of concern - assuming AutoMapper has any valid use at all, then within that usage, one may want subproperties to be cloned instead of copied by reference. – Josh Sutterfield Nov 09 '21 at 21:14