在Silverlight中使用反射进行深拷贝的扩展方法?

9 浏览
0 Comments

在Silverlight中使用反射进行深拷贝的扩展方法?

我想要找一个通用的扩展方法,使用反射创建一个对象的深拷贝,以适用于Silverlight。在Silverlight中,使用序列化进行深拷贝并不理想,因为它在部分信任模式下运行,而BinaryFormatter不存在。我也知道相比于序列化,使用反射进行克隆会更快。\n拷贝公共、私有和受保护的字段,并且递归地拷贝对象中的对象,同时还能处理集合、数组等,这样的方法会很好。\n我在网上搜索,只能找到使用反射进行浅拷贝的实现。我不明白为什么会这样,因为你可以直接使用MemberwiseClone,所以对我来说,这些实现是无用的。\n谢谢。

0
0 Comments

问题的出现原因:在Silverlight中,无法使用BinaryFormatter进行序列化和反序列化操作,因此无法直接使用上述代码来实现深拷贝。

解决方法:使用Reflection进行深拷贝操作。下面是一个Silverlight的扩展方法示例,使用Reflection实现了一个DeepCopy方法:

public static class ObjectExtensions
{
    public static T DeepCopy(this T instance)
    {
        if (instance == null)
            return default(T);
        var type = instance.GetType();
        if (type.IsValueType || type == typeof(string))
            return instance;
        var copy = Activator.CreateInstance(type);
        foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
        {
            var fieldValue = field.GetValue(instance);
            var clonedFieldValue = fieldValue.DeepCopy();
            field.SetValue(copy, clonedFieldValue);
        }
        return (T)copy;
    }
}

通过上述扩展方法,我们可以在Silverlight中进行深拷贝操作。该方法首先判断要拷贝的对象是否为值类型或字符串类型,如果是,则直接返回该对象。如果不是,则通过反射创建一个新的对象,并遍历原对象的字段,递归地对字段进行深拷贝操作,并将拷贝后的值设置到新创建的对象中。

需要注意的是,该方法只适用于可序列化对象,对于非可序列化的对象(例如用户控件),无法进行深拷贝操作。

0
0 Comments

在Silverlight中使用反射进行深拷贝的问题是,原始的cloneObject方法只能适用于没有参数的构造函数的对象。如果要使用需要构造函数参数的对象,需要传入一个object[]数组作为参数,并使用不同的Activator.CreateInstance方法的重载。

解决方法是修改cloneObject方法,使用递归和检查属性是否是集合来实现深拷贝。这样可以确保所有的属性和属性中的属性都被正确地拷贝。

具体代码如下:

using System.Reflection;
using System.Collections.Generic;
using System.Threading;
public static class DeepCopyExtension
{
    private readonly static object _lock = new object();
    public static T DeepCopy(this T original, List propertyExcludeList)
    {
        try
        {
            Monitor.Enter(_lock);
            T copy = Activator.CreateInstance();
            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))
                    {
                        if (pi.PropertyType.IsValueType || pi.PropertyType == typeof(string))
                        {
                            pi.SetValue(copy, pi.GetValue(original, null), null);
                        }
                        else
                        {
                            object nestedCopy = pi.GetValue(original, null).DeepCopy(propertyExcludeList);
                            pi.SetValue(copy, nestedCopy, null);
                        }
                    }
                }
            }
            return copy;
        }
        finally
        {
            Monitor.Exit(_lock);
        }
    }
}

这样,我们就可以使用DeepCopy方法对对象进行深拷贝,确保所有的属性和属性中的属性都被正确地拷贝。

0
0 Comments

问题的原因是在Silverlight中,我们需要对数据合同对象进行深拷贝,但是常用的深拷贝方法只适用于可序列化的类。而解决方法则是使用反射和扩展方法来实现深拷贝。

在Silverlight中,我们通常使用DataContractSerializer来实现深拷贝。上述给出了一个帮助方法Clone,通过将对象序列化为内存流,再反序列化出一个新的对象来实现深拷贝。这个方法可以通过传入泛型参数T和源对象source来进行使用。

但是,这个方法仅适用于可序列化的类。如果尝试对不可序列化的类进行深拷贝,就会出现问题。因此,我们需要找到一种方法来处理不可序列化的类。

另外,对于数组和列表,这个深拷贝方法是如何处理的呢?它是复制数组/列表的引用,还是重新创建了一个新的数组/列表并复制其中的元素?换句话说,如果将包含列表的类A复制到类B中,是否修改类B也会影响到类A中的列表?

以上就是问题的原因和解决方法的概述。下面将按照中文输出要求整理成一篇文章。

深度拷贝是在软件开发中常用的一种技术,它可以创建一个新的对象,该对象的属性值与原始对象完全相同,但是两个对象在内存中具有不同的引用。在Silverlight中,我们通常使用DataContractSerializer来实现深拷贝。然而,这种方法只适用于可序列化的类。

问题的出现是因为在Silverlight中,我们需要对数据合同对象进行深拷贝,但是常用的深拷贝方法只适用于可序列化的类。因此,我们需要找到一种方法来处理不可序列化的类。

为了解决这个问题,我们可以使用反射和扩展方法来实现深拷贝。具体的解决方法是创建一个扩展方法Clone,该方法可以对任意类型的对象进行深拷贝。该方法使用反射来获取对象的类型信息,并使用DataContractSerializer来实现序列化和反序列化。通过将对象序列化为内存流,再反序列化出一个新的对象来实现深拷贝。这样,即使对象不可序列化,也可以通过该方法进行深拷贝操作。

以下是使用扩展方法Clone进行深拷贝的示例代码:

public static T Clone(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);
    }
}

可以通过将源对象传递给扩展方法Clone来实现深拷贝,例如:

var clone = CloneHelper.Clone(dtoVar);

除了解决不可序列化类的深拷贝问题,这个方法还可以处理数组和列表。具体来说,它会重新创建一个新的数组/列表,并复制其中的元素,而不是简单地复制数组/列表的引用。因此,即使将包含列表的类A复制到类B中,修改类B的列表不会影响到类A中的列表。

总结起来,通过使用反射和扩展方法,我们可以在Silverlight中实现对不可序列化类的深拷贝。这种方法不仅适用于可序列化的类,还可以处理数组和列表,确保在进行深拷贝时不会影响到原始对象。

0