简体   繁体   English

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

[英]Deep Copy using Reflection in an Extension Method for Silverlight?

So I'm trying to find a generic extension method that creates a deep copy of an object using reflection, that would work in Silverlight. 所以我试图找到一个通用的扩展方法,它使用反射创建一个对象的深层副本,可以在Silverlight中使用。 Deep copy using serialization is not so great in Silverlight, since it runs in partial trust and the BinaryFormatter does not exist. 使用序列化的深层复制在Silverlight中并不是那么好,因为它以部分信任方式运行并且BinaryFormatter不存在。 I also know that reflection would be faster then serialization for cloning. 我也知道反射会比克隆序列化更快。

It would be nice to have a method that works to copy public, private and protected fields, and is recursive so that it can copy objects in objects, and that would also be able to handle collections, arrays, etc. 有一个方法可以复制公共,私有和受保护的字段,并且是递归的,这样它就可以复制对象中的对象,并且还可以处理集合,数组等。

I have searched online, and can only find shallow copy implementations using reflection. 我在线搜索过,只能使用反射找到浅拷贝实现。 I don't understand why, since you can just use MemberwiseClone, so to me, those implementations are useless. 我不明白为什么,因为你可以使用MemberwiseClone,所以对我来说,这些实现是没用的。

Thank You. 谢谢。

Required Namespaces: 必需的命名空间:

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

Method: 方法:

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

This is not specific to Silverlight in any way - it is just plain Reflection. 这在任何方面都不是特定于Silverlight的 - 它只是简单的反射。

As written it will only work with objects that have a parameterless constructor. 如上所述,它只适用于具有无参数构造函数的对象。 To use objects that require constructor parameters, you will need to pass in an object[] with the parameters, and use a different overload of the Activator.CreateInstance method eg 要使用需要构造函数参数的对象,您需要使用参数传入object [],并使用Activator.CreateInstance方法的不同重载,例如

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

The propertyExcludeList parameter is a list of property names that you wish to exclude from the copy, if you want to copy all properties just pass an empty list eg propertyExcludeList参数是您希望从副本中排除的属性名称列表,如果要复制所有属性,只需传递一个空列表,例如

new List<string>()

For data contract objects we have used the following helper method for deep cloning within Silverlight: 对于数据协定对象,我们在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);
            }
        }

Used like this: 像这样使用:

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

Can't you just use regular .NET reflection? 你不能只使用常规的.NET反射吗? Serialize your object to a MemoryStream and then deserialize it back. 将对象序列化为MemoryStream ,然后将其反序列化。 This will create a deep copy (ultimately using reflection) and will require hardly any code on your part: 这将创建一个深层副本(最终使用反射),并且几乎不需要您的任何代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM