2012-11-02 23 views
2

所以我試圖找到一種通用的擴展方法,它使用反射創建對象的深層副本,這將在Silverlight中起作用。使用序列化的深拷貝在Silverlight中並不是很好,因爲它在部分信任下運行,並且BinaryFormatter不存在。我也知道,爲克隆序列化反射會更快。在Silverlight的擴展方法中使用反射進行深度複製?

這將是不錯的作品複製公共,私人和保護的領域,並且是遞歸,以便它可以在對象複製對象的方法,而這也將能夠處理集合,數組等

我在網上搜索,只能找到使用反射的淺拷貝實現。我不明白爲什麼,因爲你可以使用MemberwiseClone,所以對我來說,這些實現是沒用的。

謝謝。

回答

3

對於數據的合同對象,我們一直使用深克隆以下helper方法中的Silverlight:

public static T Clone<T>(T source) 
     { 

      DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       serializer.WriteObject(ms, source); 
       ms.Seek(0, SeekOrigin.Begin); 
       return (T)serializer.ReadObject(ms); 
      } 
     } 

像這樣來使用:

var clone = CloneHelper.Clone<MyDTOType>(dtoVar); 
+0

這是基於序列化的,它會在不可序列化的類上工作嗎? – Kira

+1

可能不是。 http://msdn.microsoft.com/en-us/library/ms731923(v=vs.110).aspx –

+0

我這樣想,謝謝你的鏈接 – Kira

2

難道你不能只使用常規的.NET反射嗎?將您的對象序列化爲MemoryStream,然後將其反序列化。這將創建一個深拷貝(最終使用反射),並要求幾乎沒有任何您的部分代碼:

T DeepCopy<T>(T instance) 
{ 
    BinaryFormatter formatter=new BinaryFormatter(); 

    using(var stream=new MemoryStream()) 
    { 
    formatter.Serialize(stream, instance); 
    stream.Position=0; 

    return (T)formatter.Deserialize(stream); 
    } 
} 
+1

不,BinaryFormatter的不Silverlight的存在。 –

+1

這對於不可序列化的對象等用戶控件不起作用! – IremadzeArchil19910311

3

必需名稱空間:

using System.Reflection; 
using System.Collections.Generic; 

方法:

private readonly static object _lock = new object(); 

    public static T cloneObject<T>(T original, List<string> propertyExcludeList) 
    { 
     try 
     { 
      Monitor.Enter(_lock); 
      T copy = Activator.CreateInstance<T>(); 
      PropertyInfo[] piList = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
      foreach (PropertyInfo pi in piList) 
      { 
       if (!propertyExcludeList.Contains(pi.Name)) 
       { 
        if (pi.GetValue(copy, null) != pi.GetValue(original, null)) 
        { 
         pi.SetValue(copy, pi.GetValue(original, null), null); 
        } 
       } 
      } 
      return copy; 
     } 
     finally 
     { 
      Monitor.Exit(_lock); 
     } 
    } 

這不是以任何方式特定於Silverlight - 它只是普通的Reflection。

正如所寫的,它只能用於具有無參數構造函數的對象。要使用需要構造函數參數的對象,您需要傳入一個帶有參數的對象[],並使用Activator.CreateInstance方法的不同重載,例如

T copy = (T)Activator.CreateInstance(typeof(T), initializationParameters); 

的propertyExcludeList參數是您希望從副本排除,如果要複製所有屬性只是傳遞一個空的列表例如屬性名稱的列表

new List<string>() 
+0

我得到'System.ArgumentException被用戶代碼未處理 消息=找不到屬性集合方法。「 –

+4

這是一個淺拷貝。它需要遞歸,並檢查一個屬性是否是一個集合是一個深層副本。 – xr280xr