public override object ExtractObject(Type requestedType)
            {
                object buildObject;

                if (IsReferedMultipleTimes)
                {
                    if (ParentGraph.TryGetObjectForRefId(RefId, out buildObject))
                    {
                        return(buildObject);
                    }
                }

                Type typeToBuild = requestedType;

                if (ObjectType != null)
                {
                    Type myType = ObjectType.ClassType;
                    if (requestedType != null && !requestedType.IsAssignableFrom(myType))
                    {
                        throw new Exception("Unable to build object. Requested on type but data has another type");                             //TODO better exception
                    }
                    typeToBuild = myType;
                }

                if (typeToBuild == null)
                {
                    throw new Exception("Missing type information. Unable to build object");                            //TODO better exception
                }
                if (typeToBuild.IsAbstract || typeToBuild.IsInterface)
                {
                    throw new Exception("Cannot create a direct instance of a abstract or interface");                          //TODO better exception
                }
                if (typeToBuild.IsArray || typeToBuild.IsPrimitiveData())
                {
                    //Handle Boxed Value Types
                    IGraphNode boxedValue = m_fields[DEFAULT_BOXED_VALUE_FIELD_NAME];
                    return(boxedValue.RebuildObject(typeToBuild));
                }

                buildObject = SerializationServices.GetUninitializedObject(typeToBuild);
                ParentGraph.LinkObjectToNode(this, buildObject);

                var surrogate = SerializationServices.GetDefaultSerializationSurrogate(typeToBuild);

                surrogate.SetObjectData(ref buildObject, this);
                return(buildObject);
            }
Exemplo n.º 2
0
        public IGraphNode BuildNode(object obj, Type fieldType)
        {
            if (obj == null)
            {
                return(null);
            }

            IGraphNode result;
            Type       objType = obj.GetType();

            if (typeof(Type).IsAssignableFrom(objType))
            {
                return(GetTypeEntry((Type)obj));
            }

            var formatter = GetFormatter(objType);

            if (formatter != null)
            {
                var node = formatter.ObjectToGraphNode(obj, this);
                var fieldTypeFormatter = fieldType != null?GetFormatter(fieldType) : null;

                if (formatter != fieldTypeFormatter)
                {
                    //Value needs to be boxed
                    ObjectGraphNode box = node as ObjectGraphNode;
                    if (box == null)
                    {
                        box = (ObjectGraphNode)CreateObjectData();
                        box[DEFAULT_BOXED_VALUE_FIELD_NAME] = node;
                    }

                    if (box.ObjectType == null)
                    {
                        box.ObjectType = GetTypeEntry(objType);
                    }
                    return(box);
                }
                return(node);
            }

            if (objType.IsArray || objType.IsPrimitiveData())
            {
                //Boxable Values (arrays, bools, numbers, strings)
                IGraphNode valueNode;
                if (objType.IsArray)
                {
                    Type elemType            = objType.GetElementType();
                    ISequenceGraphNode array = BuildSequenceNode();
                    IEnumerator        it    = ((IEnumerable)obj).GetEnumerator();
                    while (it.MoveNext())
                    {
                        IGraphNode elem = BuildNode(it.Current, elemType);
                        array.Add(elem);
                    }
                    valueNode = array;
                }
                else
                {
                    //Primitive data type
                    if (objType == typeof(string))
                    {
                        valueNode = BuildStringNode(obj as string);
                    }
                    else
                    {
                        if (objType.IsEnum)
                        {
                            obj = Convert.ChangeType(obj, ((Enum)obj).GetTypeCode());
                        }

                        valueNode = BuildPrimitiveNode(obj as ValueType);
                    }
                }

                if (objType != fieldType)
                {
                    //Value needs to be boxed
                    var boxNode = CreateObjectData();
                    boxNode.ObjectType = GetTypeEntry(objType);
                    boxNode[DEFAULT_BOXED_VALUE_FIELD_NAME] = valueNode;
                    valueNode = boxNode;
                }

                result = valueNode;
            }
            else
            {
                //Non-Boxable Values (structs and objects)
                IObjectGraphNode objReturnData;
                bool             extractData = true;
                if (objType.IsValueType)
                {
                    //Structure
                    objReturnData = CreateObjectData();
                }
                else
                {
                    //Classes
                    if (!GetObjectNode(obj, out objReturnData))
                    {
                        extractData = false;
                    }
                }

                if (extractData)
                {
                    var surrogate = SerializationServices.GetDefaultSerializationSurrogate(objType);
                    surrogate.GetObjectData(obj, objReturnData);
                }

                if ((objReturnData.ObjectType == null) && (objType != fieldType))
                {
                    objReturnData.ObjectType = GetTypeEntry(objType);
                }

                result = objReturnData;
            }
            return(result);
        }