private void WriteProperty(XmlMetaProperty property, IPersistEntity entity, XmlWriter output) { var propVal = property.MetaProperty.PropertyInfo.GetValue(entity, null); //handling of XML attributes is baked before if (property.IsAttributeValue) { property.AttributeSetter(propVal, output); return; } var propType = property.MetaProperty.PropertyInfo.PropertyType; var propName = property.MetaProperty.PropertyInfo.Name; var attr = property.MetaProperty.EntityAttribute; WriteProperty(propName, propType, propVal, output, null, attr); }
private void WriteProperties(IPersistEntity entity, XmlWriter output, ExpressType expressType) { List <XmlMetaProperty> properties; if (!_propertiesCache.TryGetValue(expressType.Type, out properties)) { properties = XmlMetaProperty.GetProperties(expressType, _conf); //cache _propertiesCache.Add(expressType.Type, properties); } foreach (var property in properties) //only write out persistent attributes, ignore inverses { WriteProperty(property, entity, output); } }
private void WriteProperty(string propName, Type propType, object propVal, XmlWriter output, int[] pos, EntityAttributeAttribute attr, bool wrap = false) { //don't write anything if this is uninitialized optional item set var optSet = propVal as IOptionalItemSet; if (optSet != null && !optSet.Initialized) { return; } //null or a value type that maybe null, need to write out sets and lists if they are mandatroy but empty if (propVal == null) { if (!typeof(IExpressEnumerable).GetTypeInfo().IsAssignableFrom(propType) || attr.State != EntityAttributeState.Mandatory) { return; } //write out empty mandatory set with proper enumeration type output.WriteStartElement(propName); //output.WriteAttributeString("cType", attr.ListType); output.WriteEndElement(); return; } if (propType.GetTypeInfo().IsInterface&& typeof(IExpressSelectType).GetTypeInfo().IsAssignableFrom(propType)) // a select type get the type of the actual value { var realType = propVal.GetType(); var exprType = _metadata.ExpressType(realType); var realName = exprType != null ? exprType.ExpressName : realType.Name; output.WriteStartElement(propName); WriteProperty(realName, realType, propVal, output, null, attr, true); output.WriteEndElement(); return; } //make sure we don't mess around with nullables propType = XmlMetaProperty.GetNonNullableType(propType); if (typeof(IExpressValueType).GetTypeInfo().IsAssignableFrom(propType)) { var cpl = propVal as IExpressComplexType; if (cpl != null) { var expT = _metadata.ExpressType(propVal.GetType()); if (expT != null && expT.UnderlyingType != null && typeof(IEnumerable <IPersistEntity>).GetTypeInfo().IsAssignableFrom(expT.UnderlyingType)) { output.WriteStartElement(expT.ExpressName + (wrap ? "-wrapper" : "")); var idx = new[] { 0 }; foreach (var ent in cpl.Properties.Cast <IPersistEntity>()) { WriteEntity(ent, output, false, idx); idx[0]++; } output.WriteEndElement(); return; } } var valString = cpl == null ? propVal.ToString() : string.Join(" ", cpl.Properties); output.WriteStartElement(propName + (wrap ? "-wrapper" : "")); if (pos != null) { output.WriteAttributeString("pos", string.Join(" ", pos)); } output.WriteValue(valString); output.WriteEndElement(); return; } if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(propType) && propType != typeof(string)) { //special case for IfcRelDefinesByProperties //if (propName == "RelatedObjects" && entity.ExpressType.Name == "IfcRelDefinesByProperties") if (attr.MaxCardinality != null && attr.MaxCardinality.Length == 1 && attr.MaxCardinality[0] == 1) //list which shouldn't have more than 1 element in is serialized as a single element { propVal = ((IEnumerable)propVal).Cast <object>().FirstOrDefault(); var relEntity = propVal as IPersistEntity; if (relEntity == null) { return; } WriteEntity(relEntity, output, false, null, propName); return; } var propValEnum = ((IEnumerable)propVal).Cast <object>().ToList(); //inverse attribute with no values if (attr.Order < 0 && !propValEnum.Any()) { return; } var idx = new List <int>(pos ?? new int[] {}) { 0 }; var depth = idx.Count - 1; if (depth == 0) { output.WriteStartElement(propName); //output.WriteAttributeString(_nsPrefix, "cType", _ns, attr.ListType); } foreach (var item in propValEnum) { var expT = _metadata.ExpressType(item.GetType()); var name = expT != null ? expT.ExpressName : item.GetType().Name; WriteProperty(name, item.GetType(), item, output, idx.ToArray(), attr, true); idx[depth]++; } if (depth == 0) { output.WriteEndElement(); } return; } if (typeof(IPersistEntity).GetTypeInfo().IsAssignableFrom(propType)) { var persistEntity = (IPersistEntity)propVal; WriteEntity(persistEntity, output, false, pos, propName); return; } //this will only be called from within the enumeration //as otherwise it will be serialized as XML attribute before if (propType.GetTypeInfo().IsValueType || typeof(string) == propType || typeof(byte[]) == propType) { var pInfoType = propVal.GetType(); string pValue; if (pInfoType.GetTypeInfo().IsEnum) //convert enum { output.WriteStartElement(propName); pValue = propVal.ToString().ToLower(); } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Boolean)) { output.WriteStartElement("boolean-wrapper"); pValue = (bool)propVal ? "true" : "false"; } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Double) || pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Single)) { output.WriteStartElement("double-wrapper"); pValue = string.Format(new Part21Formatter(), "{0:R}", propVal); } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Int16)) { output.WriteStartElement("integer-wrapper"); pValue = propVal.ToString(); } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Int32) || pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(Int64)) { output.WriteStartElement("long-wrapper"); pValue = propVal.ToString(); } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(String)) //convert string { output.WriteStartElement("string-wrapper"); pValue = string.Format(new Part21Formatter(), "{0}", propVal); } else if (pInfoType.GetTypeInfo().UnderlyingSystemType == typeof(byte[])) { output.WriteStartElement("hexBinary-wrapper"); var ba = (byte[])propVal; var hex = new System.Text.StringBuilder(ba.Length * 2); foreach (byte b in ba) { hex.AppendFormat("{0:X2}", b); } pValue = hex.ToString(); } else { throw new NotSupportedException(string.Format("Invalid Value Type {0}", pInfoType.Name)); } output.WriteAttributeString("pos", string.Join(" ", pos)); output.WriteValue(pValue); output.WriteEndElement(); return; } #if DEBUG throw new Exception("Unexpected type"); #endif }
private static void SetAttributeValueHandler(XmlMetaProperty metaProperty, List <entity> typeConfigurarions) { //all value types will be serialized as attributes. Nullable<> is also value type which is correct for this. var type = metaProperty.MetaProperty.PropertyInfo.PropertyType; type = GetNonNullableType(type); var propName = metaProperty.MetaProperty.PropertyInfo.Name; if (type.IsValueType || type == typeof(string)) { if (typeof(IExpressComplexType).IsAssignableFrom(type)) { metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } writer.WriteAttributeString(propName, string.Join(" ", ((IExpressComplexType)value).Properties)); }; } else if (type.IsEnum) { metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } writer.WriteAttributeString(propName, (Enum.GetName(type, value) ?? "").ToLowerInvariant()); }; } else { metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } writer.WriteAttributeString(propName, value.ToString()); }; } return; } //lists of value types will be serialized as lists. If this is not an IEnumerable this is not the case if (!typeof(IEnumerable).IsAssignableFrom(type) || !type.IsGenericType) { return; } var genType = type.GetGenericArguments()[0]; if (genType.IsValueType || genType == typeof(string)) { if (IsStringCompatible(genType)) { //check type configuration if (typeConfigurarions != null && typeConfigurarions.Any(conf => conf.TaggLessAttributes .Any(a => a.@select == propName))) { metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } writer.WriteAttributeString(propName, string.Join(" ", ((IEnumerable)value).Cast <object>())); }; } //default for string is to be in a separate tags as strings might contain spaces which are //used as a list separators in attribute lists return; } metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } writer.WriteAttributeString(propName, string.Join(" ", ((IEnumerable)value).Cast <object>())); }; return; } //rectangular nested lists shall also be serialized as attribute if defined in configuration if (typeof(IEnumerable).IsAssignableFrom(genType) && typeConfigurarions != null && typeConfigurarions.Any(conf => conf.TaggLessAttributes .Any(a => a.@select == propName))) { metaProperty.AttributeSetter = (value, writer) => { if (value == null) { return; } var enumeration = ((IEnumerable)value).Cast <IEnumerable>().SelectMany(o => o.Cast <object>()); writer.WriteAttributeString(propName, string.Join(" ", enumeration)); }; } }