private static void InitializeClone(object source, object clone, Type type) { CloneableAttribute attribute = (CloneableAttribute)type.GetCustomAttributes(typeof(CloneableAttribute), false)[0]; MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (attribute.UseDefaultConstructor) { bool foundMethod = false; foreach (MethodInfo method in methods) { if (method.IsDefined(typeof(CloneInitializeAttribute), false)) { method.Invoke(clone, new object[] { source, _context }); foundMethod = true; break; } } if (!foundMethod) { // if there was no CloneInitialize method, we assume we are just to clone the fields. CloneFields(source, clone, type); } } foreach (MethodInfo method in methods) { if (method.IsDefined(typeof(OnCloneCompleteAttribute), false)) { method.Invoke(clone, Type.EmptyTypes); break; } } }
private static object CloneInternal(object source) { Platform.CheckForNullReference(source, "source"); object[] attributes = source.GetType().GetCustomAttributes(typeof(CloneableAttribute), false); if (attributes.Length == 0) { return(null); } object clone; CloneableAttribute attribute = (CloneableAttribute)attributes[0]; if (attribute.UseDefaultConstructor) { ConstructorInfo info = source.GetType().GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null); if (info == null) { throw new CloningException( "No default constructor found; the input object must have a default constructor" + " with the appropriate reflection permission."); } try { clone = info.Invoke(null); } catch (Exception e) { throw new CloningException( "An error occurred while executing the default constructor;" + " insure the class has the appropriate reflection permissions.", e); } } else { ConstructorInfo info = source.GetType().GetConstructor( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { source.GetType(), typeof(ICloningContext) }, null); if (info == null) { throw new CloningException( "The input object must have a constructor with the correct cloning signature and " + "reflection permission. See the class documentation for more details."); } try { clone = info.Invoke(new object[] { source, _context }); } catch (Exception e) { throw new CloningException( "An error occurred while executing the cloning constructor; " + "insure the class has the appropriate reflection permissions.", e); } } Platform.CheckForNullReference(clone, "clone"); if (clone.GetType() != source.GetType()) { throw new CloningException( string.Format("The cloned object is not the same type as the source object ({0} != {1}).", clone.GetType().FullName, source.GetType().FullName)); } //Trace.WriteLine(String.Format("CloneCreated: {0}", clone.GetType().FullName)); foreach (Type type in WalkCloneHierarchy(clone.GetType())) { InitializeClone(source, clone, type); //Trace.WriteLine(String.Format("InitializeClone: {0}", type.FullName)); } return(clone); }