Patrick Desjardins Blog
Patrick Desjardins picture from a conference

How to clone with Silverlight without ICloneable?

Posted on: 2011-10-13

The .Net Framework allow to clone ICloneable interface. This interface has a single method that is Clone. This interface is not available in Silverlight. The reason is that Microsoft have found that since it does not provide specification between deep copy or shallow copy that it was useless to port this interface into the Silverlight SDK. In fact, this interface has been questionable since a long time ago.

An other way to clone is to serialize and deserialize your object. By using this mechanism all references are not there but the value are. The problem, is that Silverlight does not have the System.Runtime.Serialization has you may know in the .Net standard framework. You won't fine the the IFormatter interface neither the BinaryFormatter class.

So, how to clone an object in Silverlight?

Here is a cloning method that is an extension for every object. It uses reflection to do it's cloning. This is not a deep copy!

 public static class CloningExtension {
  public static T Clone<T>(this T source) {
    T cloned = (T) Activator.CreateInstance(source.GetType());
    foreach (PropertyInfo curPropInfo in source.GetType().GetProperties()) {
      if (curPropInfo.GetGetMethod() != null && (curPropInfo.GetSetMethod() != null)) {
        // Handle Non-indexer properties
        if (curPropInfo.Name != "Item") {
          // get property from source object
          getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
          // clone if needed
          if (getValue != null && getValue is DependencyObject)
          getValue = Clone((DependencyObject) getValue);
          // set property on cloned
          curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
          }
          // handle indexer
          else {
            // get count for indexer
            int numberofItemInColleciton =(int)curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
            // run on indexer
            for (int i = 0; i < numberofItemInColleciton; i++) {
              // get item through Indexer object
              getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
              // clone if needed
              if (getValue != null && getValue is DependencyObject)
                getValue = Clone((DependencyObject) getValue);
              // add item to collection
              curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
            }
          }
        }
      }
    return cloned;
  }
}

If you want more information you can read this forum thread.