Esempio n. 1
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);
                }
            }
        }