所以我试图找到一个通用的扩展方法,它使用反射创建一个对象的深层副本,可以在Silverlight中使用。使用序列化的深层复制在Silverlight中并不是那么好,因为它以部分信任方式运行并且BinaryFormatter不存在。我也知道,反射会比克隆序列化更快。
有一个方法可以复制公共,私有和受保护的字段,并且是递归的,这样它就可以复制对象中的对象,并且还可以处理集合,数组等。
我在线搜索过,只能使用反射找到浅拷贝实现。我不明白为什么,因为你可以使用MemberwiseClone,所以对我来说,这些实现是没用的。
谢谢。
答案 0 :(得分: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的 - 它只是简单的反思。
如上所述,它只适用于具有无参数构造函数的对象。要使用需要构造函数参数的对象,您需要使用参数传入object [],并使用Activator.CreateInstance方法的不同重载,例如。
T copy = (T)Activator.CreateInstance(typeof(T), initializationParameters);
propertyExcludeList参数是您希望从副本中排除的属性名称列表,如果要复制所有属性,只需传递一个空列表,例如。
new List<string>()
答案 1 :(得分:3)
对于数据协定对象,我们在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);
答案 2 :(得分: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);
}
}