在 C# 中克隆具有 DataTable 和其他对象作为 属性 的复杂对象

Cloning Complex Object having DataTable and other object as property in C#

我想深入复制具有 DataTable 的复杂 C# 对象,因为 property.It 抛出错误,因为 "Table SalesData does not belong to this DataSet."

这是我的 C# 对象:

public class Foo
{
    public VehicleDetails VehicleDetails { get; set; }
    public VehicleCondition VehicleCondition { get; set; }

    public string Zipcode { get; set; }
    public string StateCode { get; set; }
    public DataTable SalesData { get; set; }
    public DataTable OtherDataTable { get; set; }
}

我使用了以下代码来克隆对象:

  public static T CloneFullObject<T>(T i)
    {
        if (Object.ReferenceEquals(i, null)) return default(T);

        var x = new XmlSerializer(i.GetType());
        using (var m = new MemoryStream())
        {
            x.Serialize(m, i);
            m.Seek(0, SeekOrigin.Begin);
            return (T)x.Deserialize(m);
        }
    }

我正在创建对象为:

   Foo foo = new Foo();

   VehicleDetails vehicleDetail = new VehicleDetails();
   // Fill vehicleDetail object

    VehicleCondition vehicleCondition = new VehicleCondition ();
   // Fill vehicleCondition object
   foo.VehicleDetails = vehicleDetail;
   foo.VehicleCondition = vehicleCondition;

   DataTable salesData = getDataTable();
   salesData.TableName = "salesData";
   foo.SalesData = salesData;

   DataTable otherData = getDataTable();
   salesData.TableName = "otherData";
   foo.OtherDataTable = salesData;

下面的代码抛出错误:

       System.InvalidOperationException: There was an error generating the XML document. ---> System.ArgumentException: Table salesData does not belong to this DataSet.

Foo clonefullObject = CloneFullObject(foo);

如果我在克隆对象之前遗漏了什么,请帮忙。

注意:两个数据表都有值并且不为空。

编辑: class Foo 具有一些复杂的属性,例如:

    private int _mileage;
    public void SetMileage(int mileage) { _mileage = mileage; }
    private int _expectedMileage;
    public void SetExpectedMileage(int mileage) { _expectedMileage =       mileage; }

    public int GetMileage(bool flag)
    {
        return (flag)
                   ? _mileage
                   : Math.Max(_mileage, _expectedMileage);
    }

当 cloning/copying 对象时,您可以简单地 clone/copy 它们。序列化是相当昂贵的矫枉过正,尤其是在不考虑性能的情况下实现(您可以在此 SE question 中阅读更多内容)。

但是,序列化不是您的真正问题,复制具有结构和数据的 DataTable 才是。看起来你的问题并不是你的问题,你的问题是你的问题。 DataTable.Copy() 做到了所有这些。

那么怎么做呢?嗯,适当的怎么样?

实施 ICloneable interface. It is kind of clumsy as return type is object. By implementing it on sub classes you can chain it deeper. I used as for casting in sample, have in mind that it will not generate exception on type mismatch. (As usually you can read more on some old SE question) 是一种正确的方法。您可能希望也可能不希望在 DataTables 的错误状态 (null) 上生成异常。

public class Foo : ICloneable
{
    //some fields....

    private int _Bar; //private field
    public void SetBar(int value) { _Bar = value; } //Field setter        

    public object Clone()
    {
        var result = new Foo()
        {
            _Bar = _Bar, // private members are accessible from their scope, even when object is different
            Zipcode = Zipcode,
            StateCode = StateCode,
            SalesData = SalesData== null ? null : SalesData.Copy(),
            OtherDataTable = OtherDataTable == null ? null : OtherDataTable.Copy(),
            VehicleDetails = VehicleDetails.Clone() as VehicleDetails,
            VehicleCondition = VehicleCondition.Clone() as VehicleCondition,
        };

        // alternatively you can call setter methods
        result.SetBar(_Bar);

        return result;

    }
}

备注:

您应该努力以更好的风格创建对象,例如使用 Factory or at least use Object Initializer 或构造函数。

@SergeyBerezovskiy 通过建议数据模型 类 而不是完整的数据表提出了一个有效的观点。