예제 #1
0
        public void Code(ref object obj)
        {
            TypeInfo typeInfo;

            #region handle null objects

            if (obj == null)
            {
                if (TryGetTypeInfo(typeof(TypeCoder.Null), out typeInfo) &&
                    ((typeInfo.Options & TypeInfo.Option.Active) != 0))
                {
                    m_writer.Write(typeInfo.Name);
                    return;
                }
                else
                {
                    throw new Exception("cannot encode null object "
                                        + "- change by configuring coder with "
                                        + "\"coder.Add(TypeCoder.Default.Null);\"");
                }
            }

            #endregion

            Type            type = obj.GetType();
            string          typeName;
            TypeInfo.Option typeOptions = TypeInfo.Option.Size
                                          | TypeInfo.Option.Version;

            if (!TypeCoder.IsDirectlyCodeable(type))
            {
                if (HandleRef(ref obj))
                {
                    return;
                }
            }

            #region handle modified type names

            if (TryGetTypeInfo(type, out typeInfo))
            {
                typeName    = typeInfo.Name;
                typeOptions = typeInfo.Options;
            }
            else
            {
                typeName = type.AssemblyQualifiedName;
                if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)
                {
                    Report.Line("qualified name \"{0}\"", typeName);
                }
            }

            #endregion

            m_writer.Write(typeName);

            #region code version placeholder

            if ((typeOptions & TypeInfo.Option.Version) != 0)
            {
                m_versionStack.Push(m_version);
                m_version = typeInfo != null ? typeInfo.Version : 0;
                m_writer.Write(m_version);
            }

            #endregion

            #region code size placeholder

            long size          = 0;
            long sizePosition  = 0;
            long startPosition = 0;
            if ((typeOptions & TypeInfo.Option.Size) != 0)
            {
                sizePosition = m_writer.BaseStream.Position;
                m_writer.Write(size);
                startPosition = m_writer.BaseStream.Position;
            }

            #endregion

            #region code fields based on supported interface

            if (!TypeCoder.WritePrimitive(this, type, ref obj))
            {
                m_typeInfoStack.Push(typeInfo);

                if ((m_debugMode & CoderDebugMode.ReportObjects) != 0)
                {
                    Report.Line("{0,-34} 0x{1:x}", typeName, obj.GetHashCode());
                }

                var fcobj = obj as IFieldCodeable;
                if (fcobj != null)
                {
                    CodeFields(type, m_version, fcobj);
                    var tmobj = obj as ITypedMap;
                    if (tmobj != null)
                    {
                        CodeFields(type, tmobj);
                    }
                }
                else if (typeInfo.ProxyType != null)
                {
                    CodeFields(type, m_version, typeInfo.Object2ProxyFun(obj));
                }
                else
                {
                    throw new Exception("uncodeable object of type \""
                                        + typeName + '\"');
                }

                m_typeInfoStack.Pop();
            }

            #endregion

            #region backpatch size into stream

            if ((typeOptions & TypeInfo.Option.Size) != 0)
            {
                var position = m_writer.BaseStream.Position;

                size = position - startPosition;
                m_writer.BaseStream.Position = sizePosition;
                m_writer.Write(size);
                m_writer.BaseStream.Position = position;
            }
            #endregion

            #region pop version stack

            if ((typeOptions & TypeInfo.Option.Version) != 0)
            {
                m_version = m_versionStack.Pop();
            }

            #endregion
        }
예제 #2
0
        public void Code(ref object obj)
        {
            TypeInfo typeInfo;

            if (obj == null)
            {
                if (TryGetTypeInfo(typeof(TypeCoder.Null), out typeInfo) &&
                    ((typeInfo.Options & TypeInfo.Option.Active) != 0))
                {
                    AddValue(new XElement(typeInfo.XmlName));
                    return;
                }
                else
                {
                    throw new Exception("cannot encode null object "
                                        + "- change by configuring coder with "
                                        + "\"coder.Add(TypeCoder.Default.Null);\"");
                }
            }

            Type type = obj.GetType();

            if (!TypeCoder.IsDirectlyCodeable(type))
            {
                if (HandleRef(ref obj))
                {
                    return;
                }
            }

            string elementName;
            string typeName = null;

            TypeInfo.Option typeOptions = TypeInfo.Option.Size
                                          | TypeInfo.Option.Version;

            if (TryGetTypeInfo(type, out typeInfo))
            {
                elementName = typeInfo.XmlName;
                typeOptions = typeInfo.Options;
            }
            else
            {
                typeName    = type.AssemblyQualifiedName;
                elementName = "object";
                if ((m_debugMode & CoderDebugMode.ReportQualifiedNames) != 0)
                {
                    Report.Line("qualified name \"{0}\"", typeName);
                }
            }

            XElement element = new XElement(elementName);

            if (typeName != null)
            {
                element.Add(new XAttribute("type", typeName));
            }

            if ((typeOptions & TypeInfo.Option.Version) != 0)
            {
                m_versionStack.Push(m_version);
                m_version = typeInfo != null ? typeInfo.Version : 0;
                element.Add(new XAttribute("version", m_version));
            }

            if (!TypeCoder.IsDirectlyCodeable(type))
            {
                if (m_doRefs && m_writeRefNumbers)
                {
                    element.Add(new XAttribute("num", m_refs.Count - 1));
                }
            }

            m_elementStack.Push(m_element);
            m_element = element;

            #region code fields based on supported interface

            if (!TypeCoder.WritePrimitive(this, type, ref obj))
            {
                m_typeInfoStack.Push(typeInfo);

                var fcobj = obj as IFieldCodeable;
                if (fcobj != null)
                {
                    CodeFields(type, m_version, fcobj);
                    var tmobj = obj as ITypedMap;
                    if (tmobj != null)
                    {
                        CodeFields(type, tmobj);
                    }
                }
                else
                {
                    throw new Exception(string.Format("uncodeable object: {0}", obj.GetType()));
                }

                m_typeInfoStack.Pop();
            }

            #endregion

            m_element = m_elementStack.Pop();
            AddValue(element);

            if ((typeOptions & TypeInfo.Option.Version) != 0)
            {
                m_version = m_versionStack.Pop();
            }
        }