国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C# > 正文

.NET的深復(fù)制方法(以C#語(yǔ)言為例)

2019-10-29 21:20:24
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

很多時(shí)候我們復(fù)制一個(gè)對(duì)象實(shí)例A到實(shí)例B,在用實(shí)例B去做其他事情的時(shí)候,會(huì)對(duì)實(shí)例B進(jìn)行修改,為保證對(duì)B的修改不會(huì)影響到A的正常使用,就需要使用到深復(fù)制。

我在網(wǎng)上搜到一些深復(fù)制的方法,同時(shí)寫(xiě)了幾組例子對(duì)這些方法進(jìn)行測(cè)試。

我的操作系統(tǒng)版本為Win7旗艦版,.NET Framework版本是4.5

測(cè)試程序

我建了一個(gè)C#窗體應(yīng)用程序(Winform),其主窗口FormMain的Load函數(shù)內(nèi)容如下:

private void FormMain_Load(object sender, EventArgs e){ //測(cè)試1:深度復(fù)制 自定義類(lèi) try {  Console.WriteLine("=== 深度復(fù)制 自定義類(lèi) ===");  TestClass test1 = new TestClass();  test1.a = 10;  test1.b = "hello world!";  test1.c = new string[] { "x", "y", "z" };  TestClass test2 = new TestClass();  test2.a = 11;  test2.b = "hello world2!";  test2.c = new string[] { "i", "j", "k" };  test1.d = test2;  Console.WriteLine("---test1_start---");  Console.WriteLine(test1);  Console.WriteLine("---test1_end---");  TestClass test3 = (TestClass)DataManHelper.DeepCopyObject(test1);  Console.WriteLine("---test3_start---");  Console.WriteLine(test3);  Console.WriteLine("---test3_end---"); } catch (Exception ex) {  Console.WriteLine(ex.ToString()); }

    //測(cè)試2:深度復(fù)制 可序列化的自定義類(lèi)
   

 try {  Console.WriteLine("=== 深度復(fù)制 可序列化的自定義類(lèi) ===");  TestClassWithS test1 = new TestClassWithS();  test1.a = 10;  test1.b = "hello world!";  test1.c = new string[] { "x", "y", "z" };  TestClassWithS test2 = new TestClassWithS();  test2.a = 11;  test2.b = "hello world2!";  test2.c = new string[] { "i", "j", "k" };  test1.d = test2;  Console.WriteLine("---test1_start---");  Console.WriteLine(test1);  Console.WriteLine("---test1_end---");  TestClassWithS test3 = (TestClassWithS)DataManHelper.DeepCopyObject(test1);  Console.WriteLine("---test3_start---");  Console.WriteLine(test3);  Console.WriteLine("---test3_end---"); } catch (Exception ex) {  Console.WriteLine(ex.ToString()); }

    //測(cè)試3:深度復(fù)制 DataTable
  

 try {  Console.WriteLine("=== 深度復(fù)制 DataTable ===");  DataTable dtKirov = new DataTable("TestTable");  dtKirov.Columns.Add("Col1");  dtKirov.Columns.Add("Col2");  dtKirov.Columns.Add("Col3");  dtKirov.Rows.Add("1-1", "1-2", "1-3");  dtKirov.Rows.Add("2-1", "2-2", "2-3");  dtKirov.Rows.Add("3-1", "3-2", "3-3");  Console.WriteLine("=== 復(fù)制前 ===");  for (int i = 0; i < dtKirov.Columns.Count; i++)  {   Console.Write(dtKirov.Columns[i].ColumnName + "/t");  }  Console.WriteLine("/n-----------------");  for (int i = 0; i < dtKirov.Columns.Count; i++)  {   for (int j = 0; j < dtKirov.Rows.Count; j++)   {    Console.Write(dtKirov.Rows[i][j].ToString() + "/t");   }   Console.WriteLine();  }  Console.WriteLine();  DataTable dtDreadNought = (DataTable)DataManHelper.DeepCopyObject(dtKirov);  Console.WriteLine("=== 復(fù)制后 ===");  for (int i = 0; i < dtDreadNought.Columns.Count; i++)  {   Console.Write(dtDreadNought.Columns[i].ColumnName + "/t");  }  Console.WriteLine("/n-----------------");  for (int i = 0; i < dtDreadNought.Columns.Count; i++)  {   for (int j = 0; j < dtDreadNought.Rows.Count; j++)   {    Console.Write(dtDreadNought.Rows[i][j].ToString() + "/t");   }   Console.WriteLine();  }  Console.WriteLine(); } catch (Exception ex) {  Console.WriteLine(ex.ToString()); }

    //測(cè)試4:深度復(fù)制 TextBox
   

 try {  Console.WriteLine("=== 深度復(fù)制 TextBox ===");  txtTest.Text = "1234";  Console.WriteLine("復(fù)制前:" + txtTest.Text);  TextBox txtTmp = new TextBox();  txtTmp = (TextBox)DataManHelper.DeepCopyObject(txtTest);  Console.WriteLine("復(fù)制后:" + txtTmp.Text); } catch (Exception ex) {  Console.WriteLine(ex.ToString()); }

    //測(cè)試5:深度復(fù)制 DataGridView
 

 try {  Console.WriteLine("=== 深度復(fù)制 DataGridView ===");  DataGridView dgvTmp = new DataGridView();  dgvTmp = (DataGridView)DataManHelper.DeepCopyObject(dgvTest); } catch (Exception ex) {  Console.WriteLine(ex.ToString()); }}

其中txtTest是一個(gè)測(cè)試用的TextBox,dgvTmp是一個(gè)測(cè)試用的DataGridView,TestClass是一個(gè)自定義類(lèi),TestClassWithS是添加了Serializable特性的TestClass類(lèi),它們的具體實(shí)現(xiàn)如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DataCopyTest{ public class TestClass {  public int a;  public string b;  public string[] c;  public TestClass d;  public override string ToString()  {   string s = "a:" + a + "/n";   if (b != null)   {    s += "b:" + b + "/n";   }   if (c != null)   {    foreach (string tmps in c)    {     if (!string.IsNullOrWhiteSpace(tmps))     {      s += "c:" + tmps + "/n";     }    }   }   if (d != null)   {    s += d.ToString();   }   return s;  } } //支持序列化的TestClass [Serializable] public class TestClassWithS {  public int a;  public string b;  public string[] c;  public TestClassWithS d;  public override string ToString()  {   string s = "a:" + a + "/n";   if (b != null)   {    s += "b:" + b + "/n";   }   if (c != null)   {    foreach (string tmps in c)    {     if (!string.IsNullOrWhiteSpace(tmps))     {      s += "c:" + tmps + "/n";     }    }   }   if (d != null)   {    s += d.ToString();   }   return s;  } }}

我對(duì)每個(gè)搜來(lái)的深復(fù)制方法,都用了這五個(gè)類(lèi)的實(shí)例進(jìn)行深復(fù)制測(cè)試,這五個(gè)類(lèi)的特征如下:

I、對(duì)自定義類(lèi)TestClass進(jìn)行深復(fù)制測(cè)試

II、對(duì)自定義類(lèi)TestClassWithS進(jìn)行深復(fù)制測(cè)試,TestClassWithS是添加了Serializable特性的TestClass類(lèi)

III、對(duì)DataTable進(jìn)行深復(fù)制測(cè)試

IV、對(duì)控件TextBox進(jìn)行深復(fù)制測(cè)試

V、對(duì)控件DataGridView進(jìn)行深復(fù)制測(cè)試

我們通過(guò)實(shí)現(xiàn)方法DataManHelper.DeepCopyObject來(lái)進(jìn)行測(cè)試

測(cè)試深復(fù)制方法1

使用二進(jìn)制流的序列化與反序列化深度復(fù)制對(duì)象

public static object DeepCopyObject(object obj){ BinaryFormatter Formatter = new BinaryFormatter(null,   new StreamingContext(StreamingContextStates.Clone)); MemoryStream stream = new MemoryStream(); Formatter.Serialize(stream, obj); stream.Position = 0; object clonedObj = Formatter.Deserialize(stream); stream.Close(); return clonedObj;}

五個(gè)場(chǎng)景的測(cè)試結(jié)果為:

I、觸發(fā)異常SerializationException,原因是該類(lèi)不支持序列化

“System.Runtime.Serialization.SerializationException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.Runtime.Serialization.SerializationException: 程序集“DataCopyTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中的類(lèi)型“DataCopyTest.TestClass”未標(biāo)記為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, S“DataCopyTest.vshost.exe”(托管(v4.0.30319)): 已加載“C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Numerics/v4.0_4.0.0.0__b77a5c561934e089/System.Numerics.dll”
erializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 37
II、可正常復(fù)制 (√)

III、可正常復(fù)制 (√)

IV、觸發(fā)異常SerializationException,原因是該類(lèi)不支持序列化

“System.Runtime.Serialization.SerializationException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.Runtime.Serialization.SerializationException: 程序集“System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中的類(lèi)型“System.Windows.Forms.TextBox”未標(biāo)記為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 128
V、觸發(fā)異常SerializationException,原因是該類(lèi)不支持序列化

“System.Runtime.Serialization.SerializationException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.Runtime.Serialization.SerializationException: 程序集“System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”中的類(lèi)型“System.Windows.Forms.DataGridView”未標(biāo)記為可序列化。
   在 System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   在 System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 24
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 141
結(jié)論:利用序列化與反序列化到二進(jìn)制流的方法深復(fù)制對(duì)象,只有在該對(duì)象支持Serializable特性時(shí)才可使用

測(cè)試深復(fù)制方法2

public static object DeepCopyObject(object obj){ Type t = obj.GetType(); PropertyInfo[] properties = t.GetProperties(); Object p = t.InvokeMember("", System.Reflection.BindingFlags.CreateInstance, null, obj, null); foreach (PropertyInfo pi in properties) {  if (pi.CanWrite)  {   object value = pi.GetValue(obj, null);   pi.SetValue(p, value, null);  } } return p;}

五個(gè)場(chǎng)景的測(cè)試結(jié)果為:

I、不會(huì)觸發(fā)異常,但結(jié)果完全錯(cuò)誤

II、不會(huì)觸發(fā)異常,但結(jié)果完全錯(cuò)誤

III、不會(huì)觸發(fā)異常,但結(jié)果完全錯(cuò)誤

IV、Text字段賦值結(jié)果正確,但其他內(nèi)容不能保證

V、觸發(fā)異常ArgumentOutOfRangeException、TargetInvocationException

“System.ArgumentOutOfRangeException”類(lèi)型的第一次機(jī)會(huì)異常在 System.Windows.Forms.dll 中發(fā)生
“System.Reflection.TargetInvocationException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.Reflection.TargetInvocationException: 調(diào)用的目標(biāo)發(fā)生了異常。 ---> System.ArgumentOutOfRangeException: 指定的參數(shù)已超出有效值的范圍。
參數(shù)名: value
   在 System.Windows.Forms.DataGridView.set_FirstDisplayedScrollingColumnIndex(Int32 value)
   --- 內(nèi)部異常堆棧跟蹤的結(jié)尾 ---
   在 System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   在 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   在 System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   在 System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 29
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 141
結(jié)論:使用這種方法進(jìn)行所謂深復(fù)制,完全是自尋死路!

測(cè)試深復(fù)制方法3

public static object DeepCopyObject(object obj){ if (obj != null) {  object result = Activator.CreateInstance(obj.GetType());  foreach (FieldInfo field in obj.GetType().GetFields())  {   if (field.FieldType.GetInterface("IList", false) == null)   {    field.SetValue(result, field.GetValue(obj));   }   else   {    IList listObject = (IList)field.GetValue(result);    if (listObject != null)    {     foreach (object item in ((IList)field.GetValue(obj)))     {      listObject.Add(DeepCopyObject(item));     }    }   }  }  return result; } else {  return null; }}

五個(gè)場(chǎng)景的測(cè)試結(jié)果為:

I、可正常復(fù)制(√)

II、可正常復(fù)制(√)

III、未觸發(fā)異常, 復(fù)制后DataTable無(wú)行列

IV、未觸發(fā)異常,Text字段未賦值

V、未觸發(fā)異常

結(jié)論:這個(gè)方法只適用于深復(fù)制具備簡(jiǎn)單結(jié)構(gòu)的類(lèi)(如類(lèi)中只有基礎(chǔ)字段、數(shù)組等),對(duì)于不支持序列化的對(duì)象也可以進(jìn)行深復(fù)制。

測(cè)試深復(fù)制方法4

這段代碼來(lái)源同方法3

public static object DeepCopyObject(object obj){ if (obj == null)  return null; Type type = obj.GetType(); if (type.IsValueType || type == typeof(string)) {  return obj; } else if (type.IsArray) {  Type elementType = Type.GetType(    type.FullName.Replace("[]", string.Empty));  var array = obj as Array;  Array copied = Array.CreateInstance(elementType, array.Length);  for (int i = 0; i < array.Length; i++)  {   copied.SetValue(DeepCopyObject(array.GetValue(i)), i);  }  return Convert.ChangeType(copied, obj.GetType()); } else if (type.IsClass) {  object toret = Activator.CreateInstance(obj.GetType());  FieldInfo[] fields = type.GetFields(BindingFlags.Public |     BindingFlags.NonPublic | BindingFlags.Instance);  foreach (FieldInfo field in fields)  {   object fieldValue = field.GetValue(obj);   if (fieldValue == null)    continue;   field.SetValue(toret, DeepCopyObject(fieldValue));  }  return toret; } else  throw new ArgumentException("Unknown type");}

五個(gè)場(chǎng)景的測(cè)試結(jié)果為:

I、可正常復(fù)制(√)

II、可正常復(fù)制(√)

III、觸發(fā)異常MissingMethodException

“System.MissingMethodException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.MissingMethodException: 沒(méi)有為該對(duì)象定義無(wú)參數(shù)的構(gòu)造函數(shù)。
   在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
   在 System.Activator.CreateInstance(Type type)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 45
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 53
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 99
IV、未觸發(fā)異常,但Text字段也未賦值成功

V、觸發(fā)異常MissingMethodException

“System.MissingMethodException”類(lèi)型的第一次機(jī)會(huì)異常在 mscorlib.dll 中發(fā)生
System.MissingMethodException: 沒(méi)有為該對(duì)象定義無(wú)參數(shù)的構(gòu)造函數(shù)。
   在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   在 System.Activator.CreateInstance(Type type, Boolean nonPublic)
   在 System.Activator.CreateInstance(Type type)
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 45
   在 DataCopyTest.DataManHelper.DeepCopyObject(Object obj) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/DataManHelper.cs:行號(hào) 53
   在 DataCopyTest.FormMain.FormMain_Load(Object sender, EventArgs e) 位置 d:/MyPrograms/DataCopyTest/DataCopyTest/FormMain.cs:行號(hào) 141
結(jié)論:這個(gè)方法的作用類(lèi)似方法3,只能深復(fù)制基本數(shù)據(jù)類(lèi)型組成的類(lèi)

具體問(wèn)題具體分析

從上面的例子可以看出,想找一個(gè)放之四海而皆準(zhǔn)的方式去深復(fù)制所有對(duì)象是很困難的。一些使用高級(jí)語(yǔ)言特性(反射)的深復(fù)制方法,即使可以在部分類(lèi)上試用成功,也無(wú)法對(duì)所有的類(lèi)都具備十足的把握。因此我認(rèn)為應(yīng)該采取下面的方式處理對(duì)象的深復(fù)制問(wèn)題:

1、對(duì)于由基本數(shù)據(jù)類(lèi)型組成的類(lèi),為之打上Serializable標(biāo)簽,直接使用序列化與反序列化的方法進(jìn)行深復(fù)制

2、其他較為復(fù)雜的類(lèi)型如DataGridView,可根據(jù)自身情況寫(xiě)一個(gè)方法進(jìn)行深復(fù)制,之所以在這里說(shuō)要根據(jù)自身情況寫(xiě)方法,是因?yàn)樵趯?duì)很多類(lèi)進(jìn)行復(fù)制時(shí),你只需要復(fù)制對(duì)你有用的屬性就行了。如TextBox控件中,只有Text一個(gè)屬性對(duì)你是有用的,如果你需要在復(fù)制后的對(duì)象中用到Readonly等屬性的值,那么在你自己實(shí)現(xiàn)的復(fù)制方法中,也加上對(duì)這些屬性的賦值即可。這樣做還有一個(gè)好處,就是方便進(jìn)行一些定制化的開(kāi)發(fā)。

如下面這段代碼,就是對(duì)DataGridView的一個(gè)近似的深復(fù)制,這段代碼將一個(gè)DataGridView(dgv)的內(nèi)容復(fù)制到另一個(gè)DataGridView(dgvTmp)中,然后將dgvTmp傳遞給相關(guān)函數(shù)用于將DataGridView中的內(nèi)容輸出到Excel文檔:

DataGridView dgvTmp = new DataGridView();dgvTmp.AllowUserToAddRows = false; //不允許用戶(hù)生成行,否則導(dǎo)出后會(huì)多出最后一行for (int i = 0; i < dgv.Columns.Count; i++){ dgvTmp.Columns.Add(dgv.Columns[i].Name, dgv.Columns[i].HeaderText); if (dgv.Columns[i].DefaultCellStyle.Format.Contains("N")) //使導(dǎo)出Excel文檔金額列可做SUM運(yùn)算 { dgvTmp.Columns[i].DefaultCellStyle.Format = dgv.Columns[i].DefaultCellStyle.Format; } if (!dgv.Columns[i].Visible) { dgvTmp.Columns[i].Visible = false; }}for (int i = 0; i < dgv.Rows.Count; i++){ object[] objList = new object[dgv.Rows[i].Cells.Count]; for (int j = 0; j < objList.Length; j++) { if (dgvTmp.Columns[j].DefaultCellStyle.Format.Contains("N")) { objList[j] = dgv.Rows[i].Cells[j].Value; //使導(dǎo)出Excel文檔金額列可做SUM運(yùn)算 } else { objList[j] = dgv.Rows[i].Cells[j].EditedFormattedValue; //數(shù)據(jù)字典按顯示文字導(dǎo)出 } } dgvTmp.Rows.Add(objList);}

這段代碼的特點(diǎn)如下:

1、DataGridView的屬性AllowUserToAddRows要設(shè)置成false,否則導(dǎo)出到Excel文檔后,會(huì)發(fā)現(xiàn)最后會(huì)多出一個(gè)空行。

2、我們?cè)谶@里標(biāo)記了那些列是隱藏列,這樣在后面的處理中,如果要?jiǎng)h除這些列,那刪除的也是dgvTmp的列而不是dgv的列,保護(hù)了原數(shù)據(jù)。

3、對(duì)于部分?jǐn)?shù)據(jù)字典的翻譯,我們傳的不是Value而是EditedFormattedValue,這種方式直接使用了dgv在屏幕上顯示的翻譯后文字,而不是原來(lái)的數(shù)據(jù)字典值。

4、對(duì)于部分金額列,需要直接傳Value值,同時(shí)需要設(shè)置該列的DefaultCellStyle.Format,這樣可使得這些內(nèi)容在之后輸出到Excel文檔后,可做求和運(yùn)算(Excel中類(lèi)似“12,345.67”字符串是不能做求和運(yùn)算的)。 


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到c#教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 浦江县| 尼玛县| 鄯善县| 惠州市| 隆昌县| 阳城县| 天柱县| 黄浦区| 沽源县| 祁东县| 永和县| 咸丰县| 土默特右旗| 明光市| 唐海县| 泰顺县| 屯昌县| 手机| 怀仁县| 新闻| 达拉特旗| 宁远县| 双峰县| 宁海县| 靖江市| 东山县| 新河县| 沙坪坝区| 贡嘎县| 莎车县| 雷山县| 浮山县| 阳江市| 呼伦贝尔市| 大洼县| 慈利县| 确山县| 泰顺县| 宁强县| 高陵县| 湖南省|