在Silverlight的扩展方法中使用反射进行深层复制?

时间:2012-11-02 15:48:19

标签: c# silverlight reflection silverlight-5.0 deep-copy

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

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

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

谢谢。

3 个答案:

答案 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);
  }
}