【问题标题】:C# - Make copy of a big class (model) by value not referenceC# - 按值而不是引用复制大类(模型)
【发布时间】:2020-02-23 01:58:49
【问题描述】:

我通过 asp.net core mvc 做项目。当我复制模型并更改其值时,原始模型的值也在发生变化,因为它通过引用复制了模型,因此数据中的值位置是相同的。 我需要一种方法来复制与原始模型无关的模型值。

【问题讨论】:

  • 将每个属性复制或投影到一个新对象中或使用自动映射器或序列化,无论哪种方式都已被询问并搜索了很多

标签: c# entity-framework class oop


【解决方案1】:

您的问题可能有很多答案,具体取决于您要复制的对象的封装。我将假设您正在对低级实体对象而不是应该封装它的对象进行操作。如果这个假设不正确,并且它是封装实体操作的更高级别的对象,我会轻轻提醒您良好的编程实践:Martin Fowler - TellDontAsk

对于答案,我将使用下面的类来说明:

public class Student
{
    public int Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public DateTime EnrollmentDate { get; set; }
}

我假设正在发生的事情类似于以下内容:

Student john = new Student();
Student jane = john;

jane.FirstName = "Jane"; // now john.FirstName == "Jane"

您需要做的是将对象克隆到一个新的对象实例。有多种方法可以做到这一点。

选项#1:

// Create a new entity object manually assigning each value
// from the first object to the value in the new object.
var clonedStudent = new Student
{
    Id = john.Id, // Copies value not reference
    LastName = john.LastName, // string is immutable this OK
    FirstName = john.FirstName, // string is immutable this OK
    // DateTime is a struct I think so it should pass value
    EnrollmentDate = john.EnrollmentDate // Verify my assumption
};

选项 #2:

// Make Student class partial and extend it with clone method.
// This is helpful for generated entities not using the code-first approach.
public partial class Student
{
    public int Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public DateTime EnrollmentDate { get; set; }
}

public partial class Student
{
    public Student Clone()
    {
        return new Student
        {
            Id = Id, // Copies value not reference
            LastName = LastName, // string is immutable this OK
            FirstName = FirstName, // string is immutable this OK
            // DateTime is a struct I think so it should pass value
            EnrollmentDate = EnrollmentDate, // Verify my assumption
        };
    }
}

要使用它,你会写:

Student clonedStudent = john.Clone();

选项 #3:您可以使用为您进行克隆的 NuGet 包。有各种各样的人这样做。一个快速的谷歌搜索为我找到了这个。 DeepCloner

如果您要将对象从一种类型复制到另一种类型,您可能需要使用AutoMapper

注意:另外,根据您的问题,了解实体框架如何处理更改可能会很有用。

Tracking vs. No-Tracking Queries

希望对您有所帮助。

编码愉快!!!

【讨论】:

  • 我的班级太大了,里面还有其他班级,我不能单独通过每一项。
  • 我只想复制值:Class2=Class1;
  • 用户定义的类型不能重载赋值运算符来做你想要它做的事情。但是,用户定义的类型可以定义到另一种类型的隐式转换。所以答案是使用上面指定的方法之一。如果您对此不确定并想尝试,请询问有关如何进行隐式转换的另一个问题。
【解决方案2】:

选项 1 使用 AutoMapper

选项 2 使用反射创建副本

        public class PropertyCopier<TParent, TChild> where TParent : class
                                       where TChild : class
    {
        public static void Copy(TParent parent, TChild child)
        {
            var parentProperties = parent.GetType().GetProperties();
            var childProperties = child.GetType().GetProperties();

            foreach (var parentProperty in parentProperties)
            {
                foreach (var childProperty in childProperties)
                {
                    if (parentProperty.Name == childProperty.Name && parentProperty.PropertyType == childProperty.PropertyType)
                    {
                        childProperty.SetValue(child, parentProperty.GetValue(parent));
                        break;
                    }
                }
            }
        }
    }

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2011-02-07
  • 2021-08-02
  • 2017-03-15
  • 1970-01-01
相关资源
最近更新 更多