3

因此,我试图找到一种通用扩展方法,该方法可以使用反射创建对象的深层副本,该方法可以在 Silverlight 中使用。在 Silverlight 中,使用序列化的深度复制不是很好,因为它在部分信任下运行并且 BinaryFormatter 不存在。我也知道反射会比序列化克隆更快。

最好有一个方法可以复制公共、私有和受保护的字段,并且是递归的,以便它可以复制对象中的对象,并且还能够处理集合、数组等。

我在网上搜索过,只能找到使用反射的浅拷贝实现。我不明白为什么,因为你可以只使用 MemberwiseClone,所以对我来说,那些实现是没用的。

谢谢你。

4

3 回答 3

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);
于 2012-11-20T13:30:45.613 回答
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>()
于 2012-11-02T16:58:10.160 回答
2

你不能只使用常规的.NET 反射吗?将您的对象序列化为 a 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);
  }
}
于 2012-11-02T16:31:15.417 回答