将对象复制到对象(使用Automapper?)

Kri*_*s-I 63 c# automapper

我有一节课:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我有两个Person实例(person1和person2).我想将person2的内容复制到person1.我想在一个指令中制作此副本,而不是按属性制作属性:

person1.LastName = person2.LastName;
Run Code Online (Sandbox Code Playgroud)

在doc中,我看到将对象复制到另一个对象但类型不同.如何在类型相同时复制对象?

Ulf*_*edt 75

据我了解的问题,OP并不想克隆PERSON2进入一个新的实例,但要求怎样的内容复制PERSON2到一个已经存在的实例(PERSON1的).AutoMapper的Mapper.Map方法有一个重载,可以为您完成此任务:

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

注1: @ alexl的答案创建了Person实例.如果您对person1指向的实例有其他引用,那么如果将person1变量重定向到新实例,则这些引用将无法获得(可能)所需的数据更新.

注意2:您需要知道(递归)复制深度取决于AutoMapper在映射时知道的映射!
如果Person类的成员是Brain类,而你Mapper.CreateMap<Brain, Brain>();在复制数据Mapper.Map<Person, Person>(person2, person1);调用之前已经完成了,那么person1将保留其当前的Brain实例,但是这个Brain将接收person2Brain实例的成员值.那是你有一个深刻的副本.
但是如果AutoMapper在复制之前没有Brain-Brain映射,那么person1Brain成员将引用与person2引用相同的Brain实例.那就是你会得到一份浅薄的副本. 这适用于所有成员的递归应用,因此您最好确保AutoMapper具有要进行深层复制的成员类的映射,并且不具有要进行浅层复制的成员类的映射.

使用AutoMapper的另一种方法是使用反射方法.(请注意,链接中的代码执行拷贝!)

AutoMapper版本0.2中添加了 "支持填充现有对象,而不是AutoMapper创建目标对象本身" .


wal*_*wal 25

既然你问过With Automapper?我可以建议你不要使用AutoMapper吗?

而是MemberwiseClone()Clone方法中使用,例如

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

    public Person Clone()
    {
        return (Person) MemberwiseClone();
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

重要的是要注意这并没有实现原始海报希望复制person1 到其中 person2

但是,MemberwiseClone()如果您只需要复制(克隆)该对象,(并且正如@Jimmy Bogard指出的那样)使用是首选.

例如,如果你这样做:

//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)
Run Code Online (Sandbox Code Playgroud)

那么你真的应该/可以使用

//oh wait, i can just use this!
var person2 = person1.Clone()
Run Code Online (Sandbox Code Playgroud)

  • wal:MemberwiseClone创建Person的_new_实例.OP想要保持Person1指向的已存在的实例,并用Person2的值填充它.如果将Person1重定向到新实例,可能还有对Person1指向的实例的其他引用将无法获得所需的数据更新. (6认同)
  • object.MemberwiseClone()执行浅拷贝,而不是深拷贝.https://www.google.ch/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=shallow%20copy%20vs%20deep%20copy (6认同)
  • 唯一的问题是你现在声明可以克隆你的Person类型.这在语义上是不正确的,目标是从一个实例到另一个实例执行副本(而不是克隆). (4认同)
  • 您没有解释为什么不使用 AutoMapper?我是不是认为“return (Person) MemberwiseClone();”是一种不好的做法或者只是一种“代码味道”的人? (2认同)

ale*_*exl 17

Mapper.CreateMap<Person, Person>();

// Perform mapping

var person1 = Mapper.Map<Person, Person>(person2);
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 这不应该是`Mapper.Map <Person,Person>(person2,person1);`?你的方式将创建一个新的对象`person1`(在我的回答中我被杀死了;)) (16认同)
  • 对于在这里谷歌的人:Map.CreateMap 已删除,此处描述了配置映射的新方法 /sf/answers/2673601591/ (2认同)

Mov*_*GP0 8

在当前版本的AutoMapper中,不能使用静态AutoMapper.Mapper.Map方法。相反,像这样初始化一个新的映射器:

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

var mapper = new Mapper(config);

var clone = mapper.Map<Person>(person);
Run Code Online (Sandbox Code Playgroud)

通常,您希望在文件中注册映射器Startup.cs以进行依赖注入,并将其注入到您的业务类中:

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

    var mapper = new Mapper(config);

    services.AddSingleton(mapper);

    // ...
}
Run Code Online (Sandbox Code Playgroud)

重要提示: 不要在实体类中创建或注入映射器!

当然,您应该更喜欢MemberwiseClone()在简单的情况下使用。

  • @PandaWood 而不是 `var clone = Mapper.Map&lt;Person&gt;(person);` 您可以使用 `Mapper.Map(person, clone);` (2认同)