public void CodeFields(Type type, ITypedMap obj)
        {
            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);

            foreach (string fieldName in obj.FieldNames)
            {
                XElement   element   = null;
                XAttribute attribute = null;
                object     value     = obj[fieldName];
                Type       fieldType;
                string     fieldTypeName = null;
                if (!fieldTypeMap.TryGetValue(fieldName, out fieldType))
                {
                    TypeInfo typeInfo;
                    fieldType = value.GetType();
                    if (TryGetTypeInfo(fieldType, out typeInfo))
                    {
                        fieldTypeName = typeInfo.XmlName;
                    }
                    else
                    {
                        fieldTypeName = fieldType.AssemblyQualifiedName;
                    }
                    attribute = new XAttribute("type", fieldTypeName);
                }
                else
                {
                    fieldTypeName = fieldType.Name;
                }

                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))
                {
                    element = new XElement(fieldName);
                    if (attribute != null)
                    {
                        element.Add(attribute);
                    }
                    m_elementStack.Push(m_element);
                    m_element = element;
                }
                TypeCoder.Write(this, fieldType, ref value);
                if (fieldTypeName != fieldName || TypeCoder.IsDirectlyCodeable(fieldType))
                {
                    m_element = m_elementStack.Pop();
                    AddValue(element);
                }
            }
        }
示例#2
0
        public void CodeFields(Type type, ITypedMap obj)
        {
            TypeOfString fieldTypeMap = FieldTypeMap.Get(type, obj);

            m_writer.Write(obj.FieldCount);

            foreach (string fieldName in obj.FieldNames)
            {
                m_writer.Write(fieldName);
                object value            = obj[fieldName];
                bool   directlyCodeable = true;
                Type   fieldType        = null;

                if ((m_debugMode & CoderDebugMode.ReportFields) != 0)
                {
                    Report.Line("  {0}", fieldName);
                }

                // A field is directly codeable, if its type information can
                // be computed by the writer and the reader without
                // inspecting the actual field value.

                if (!fieldTypeMap.TryGetValue(fieldName, out fieldType) ||
                    (value != null && fieldType != value.GetType()) ||
                    !TypeCoder.IsDirectlyCodeable(fieldType))
                {
                    directlyCodeable = false;
                }

                // We store the directly codeable flag, so that a stored file
                // can be read, even if the class has been modified, and the
                // value of directly codeable has been changed.

                m_writer.Write(directlyCodeable);
                if (directlyCodeable)
                {
                    TypeCoder.Write(this, fieldType, ref value);
                }
                else
                {
                    Code(ref value);
                }
            }
        }
示例#3
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
        }
        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();
            }
        }