Пример #1
0
        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;
                }
            }
        }
Пример #2
0
        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);
        }