简体   繁体   中英

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. Deep copy using serialization is not so great in Silverlight, since it runs in partial trust and the BinaryFormatter does not exist. 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.

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.

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

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

new List<string>()

For data contract objects we have used the following helper method for deep cloning within 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? Serialize your object to a MemoryStream and then deserialize it back. 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);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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