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); } } }
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); } } }
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(); } }