Exemple #1
0
        public static bool TryDuplicateObject(RubyContext /*!*/ context, object obj, bool cloneSemantics, out object copy)
        {
            // Ruby value types can't be cloned
            if (RubyUtils.IsRubyValueType(obj))
            {
                copy = null;
                return(false);
            }

            IDuplicable clonable = obj as IDuplicable;

            if (clonable != null)
            {
                copy = clonable.Duplicate(context, cloneSemantics);
            }
            else
            {
                // .NET classes and library clases that doesn't implement IDuplicable:
                copy = RubySites.Allocate(context.GetClassOf(obj));
                context.CopyInstanceData(obj, copy, cloneSemantics);
            }

            // TODO: optimize
            _InitializeCopySharedSite.Target(_InitializeCopySharedSite, context, copy, obj);
            if (cloneSemantics)
            {
                context.FreezeObjectBy(copy, obj);
            }

            return(true);
        }
Exemple #2
0
        public static object DeepCopy(RubyContext /*!*/ context, object obj)
        {
            using (IDisposable handle = _infiniteCopyTracker.TrackObject(obj)) {
                if (handle == null)
                {
                    return(RubyExceptions.CreateArgumentError("unable to deep copy recursive structure"));
                }
                else
                {
                    RubyContext ec = RubyUtils.GetExecutionContext(context);

                    if (RubyUtils.IsRubyValueType(obj))
                    {
                        return(obj);
                    }

                    object copy;

                    // TODO: special case class objects:
                    RubyClass classObject = obj as RubyClass;
                    if (classObject != null)
                    {
                        copy = classObject.Duplicate();
                    }
                    else
                    {
                        copy = RubySites.Allocate(context, ec.GetClassOf(obj));
                    }

                    SymbolId[]       names   = ec.GetInstanceVariableNames(obj);
                    RubyInstanceData newVars = (names.Length > 0) ? ec.GetInstanceData(copy) : null;
                    foreach (SymbolId name in names)
                    {
                        object value;
                        if (!ec.TryGetInstanceVariable(obj, name, out value))
                        {
                            value = null;
                        }
                        else
                        {
                            value = DeepCopy(context, value);
                        }
                        newVars.SetInstanceVariable(name, value);
                    }

                    if (classObject == null)
                    {
                        // do any special copying needed for library types
                        // TODO: we still need to implement copy semantics for .NET types in general
                        IDuplicable duplicable = copy as IDuplicable;
                        if (duplicable != null)
                        {
                            duplicable.InitializeFrom(obj);
                        }
                    }
                    return(copy);
                }
            }
        }