/// <summary> /// Returns all handles that are not of type to exclude /// </summary> /// <param name="exclude"></param> /// <returns></returns> public IEnumerable <XbimGeometryHandle> Exclude(params int[] exclude) { var excludeSet = new HashSet <int>(exclude); foreach (var ex in exclude) { var type = _metadata.ExpressType((short)ex); // bugfix here: loop did not use to include all implementations, but only first level down. foreach (var sub in type.NonAbstractSubTypes) { excludeSet.Add(sub.TypeId); } } return(this.Where(h => !excludeSet.Contains(h.ExpressTypeId))); }
internal void BeginNestedType(string typeName) { var type = _metadata.ExpressType(typeName); _currentInstance = new Part21Entity((IPersist)Activator.CreateInstance(type.Type)); _processStack.Push(_currentInstance); }
public bool Resolve(ConcurrentDictionary <int, IPersistEntity> references, ExpressMetaData metadata) { IPersistEntity entity; if (references.TryGetValue(ReferenceEntityLabel, out entity)) { var pv = new PropertyValue(); pv.Init(entity); try { _referencingEntity.Parse(_referencingPropertyId, pv, _nestedIndex); return(true); } catch (Exception) { var expressType = metadata.ExpressType(_referencingEntity); //TODO put a logger message here //EsentModel.Logger.ErrorFormat("Data Error. Cannot set the property = {0} of entity #{1} = {2} to entity #{3}, schema violation. Ignored", // expressType.Properties[_referencingPropertyId+1].PropertyInfo.Name, // _referencingEntity.EntityLabel, // _referencingEntity.GetType().Name, // ReferenceEntityLabel); return(false); } } else { return(false); } }
private void WriteEntity(IPersistEntity entity, XmlWriter output, bool onlyOnce, int[] pos = null, string name = null) { var exists = _written.Contains(entity.EntityLabel); if (exists && onlyOnce) //we have already done it and nothing should be written out { return; } if (!exists) { _written.Add(entity.EntityLabel); } var expressType = _metadata.ExpressType(entity); var elementName = name ?? expressType.ExpressName; output.WriteStartElement(elementName); output.WriteAttributeString(exists ? "ref" : "id", string.Format("i{0}", entity.EntityLabel)); if (pos != null) //we are writing out a list element { output.WriteAttributeString("pos", string.Join(" ", pos)); } //specify type if it is different from the name of the element if (name != null && string.CompareOrdinal(name, expressType.ExpressName) != 0) { output.WriteAttributeString("type", Xsi, expressType.ExpressName); } //only write properties if this is the first occurence if (!exists) { WriteProperties(entity, output, expressType); } //specify this is an empty element refering to another one else { output.WriteAttributeString("nil", Xsi, "true"); } output.WriteEndElement(); }
private void SetEntityParameter(string value) { try { if (CurrentInstance.Entity != null) { CurrentInstance.ParameterSetter(CurrentInstance.CurrentParamIndex, PropertyValue, NestedIndex); } } catch (Exception) { if (ErrorCount > MaxErrorCount) { throw new XbimParserException("Too many errors in file, parser execution terminated"); } ErrorCount++; var mainEntity = _processStack.Last(); if (mainEntity != null) { var expressType = Metadata?.ExpressType(mainEntity.Entity); if (expressType != null) { var propertyName = mainEntity.CurrentParamIndex + 1 > expressType.Properties.Count ? "[UnknownProperty]" : expressType.Properties[mainEntity.CurrentParamIndex + 1].PropertyInfo.Name; Logger.ErrorFormat("Entity #{0,-5} {1}, error at parameter {2}-{3} value = {4}", mainEntity.EntityLabel, mainEntity.Entity.GetType().Name.ToUpper(), mainEntity.CurrentParamIndex + 1, propertyName, value); } else { Logger.ErrorFormat("Entity #{0,-5} {1}, error at parameter {2} value = {3}", mainEntity.EntityLabel, mainEntity.Entity.GetType().Name.ToUpper(), mainEntity.CurrentParamIndex + 1, value); } } else { Logger.Error("Unhandled Parser error, in Parser.cs SetEntityParameter"); } } if (ListNestLevel == 0) { CurrentInstance.CurrentParamIndex++; _deferListItems = false; } }
protected override void EndNestedType(string value) { try { PropertyValue.Init(_processStack.Pop().Entity); CurrentInstance = _processStack.Peek(); if (CurrentInstance.Entity != null) { CurrentInstance.ParameterSetter(CurrentInstance.CurrentParamIndex, PropertyValue, NestedIndex); } } catch (Exception) { if (ErrorCount > MaxErrorCount) { throw new XbimParserException("Too many errors in file, parser execution terminated"); } ErrorCount++; var mainEntity = _processStack.Last(); if (mainEntity != null) { var expressType = Metadata.ExpressType(mainEntity.Entity); Logger.ErrorFormat("Entity #{0,-5} {1}, error at parameter {2}-{3} value = {4}", mainEntity.EntityLabel, mainEntity.Entity.GetType().Name.ToUpper(), mainEntity.CurrentParamIndex + 1, expressType.Properties[mainEntity.CurrentParamIndex + 1].PropertyInfo.Name, value); } else { Logger.Error("Unhandled Parser error, in Parser.cs EndNestedType"); } } if (ListNestLevel == 0) { CurrentInstance.CurrentParamIndex++; _deferListItems = false; } }
private ExpressType GetExpressType(ExpressMetaData schema, string classString) { var v = schema.ExpressType(classString.ToUpper()); if (v != null) { return(v); } // warn once only; if (_failedLookupMessages.Contains(classString.ToUpper())) { return(null); } Log.Error($"{classString} is not a recognised class in {schema.Module.Name}."); _failedLookupMessages.Add(classString.ToUpper()); return(null); }
private void Write(IPersistEntity entity, XmlWriter output, int pos = -1) { if (_written.Contains(entity.EntityLabel)) //we have already done it { return; } _written.Add(entity.EntityLabel); var expressType = _metadata.ExpressType(entity); output.WriteStartElement(expressType.Type.Name); output.WriteAttributeString("id", string.Format("i{0}", entity.EntityLabel)); if (pos > -1) //we are writing out a list element { output.WriteAttributeString("pos", pos.ToString()); } IEnumerable <ExpressMetaProperty> toWrite; if (WriteInverses) { var l = new List <ExpressMetaProperty>(expressType.Properties.Values); l.AddRange(expressType.Inverses); toWrite = l; } else { toWrite = expressType.Properties.Values; } foreach (var ifcProperty in toWrite) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State != EntityAttributeState.DerivedOverride) { var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); WriteProperty(ifcProperty.PropertyInfo.Name, propType, propVal, entity, output, -1, ifcProperty.EntityAttribute); } } output.WriteEndElement(); }
private bool IsIfcProperty(string elementName, out int index, out ExpressMetaProperty prop) { ExpressType expressType; var xmlEntity = _currentNode as XmlEntity; if (xmlEntity != null && !_metadata.TryGetExpressType(elementName.ToUpper(), out expressType)) { var t = _metadata.ExpressType(xmlEntity.Entity); foreach (var p in t.Properties.Where(p => p.Value.PropertyInfo.Name == elementName)) { prop = p.Value; index = p.Key; return(true); } } prop = null; index = -1; return(false); }
private static void WriteEntity(IPersistEntity entity, TextWriter output, ExpressMetaData metadata) { var expressType = metadata.ExpressType(entity); output.Write("#{0}={1}(", entity.EntityLabel, expressType.ExpressNameUpper); var first = true; foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { if (!first) { output.Write(','); } output.Write('*'); first = false; } else { // workaround for IfcCartesianPointList3D from IFC4x1 if (entity is IfcCartesianPointList3D && ifcProperty.Name == "TagList") { continue; } var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); if (!first) { output.Write(','); } Part21Writer.WriteProperty(propType, propVal, output, null, metadata); first = false; } } output.Write(");"); }
/// <summary> /// Writes the entity to a TextWriter in the Part21 format /// </summary> /// <param name="output">The TextWriter</param> /// <param name="entity">The entity to write</param> /// <param name="metadata"></param> /// <param name="map"></param> public static void WriteEntity(IPersistEntity entity, TextWriter output, ExpressMetaData metadata, IDictionary <int, int> map = null) { var expressType = metadata.ExpressType(entity); if (map != null && map.Keys.Contains(entity.EntityLabel)) { return; //if the entity is replaced in the map do not write it } output.Write("#{0}={1}(", entity.EntityLabel, expressType.ExpressNameUpper); var first = true; foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { if (!first) { output.Write(','); } output.Write('*'); first = false; } else { var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); if (!first) { output.Write(','); } WriteProperty(propType, propVal, output, map, metadata); first = false; } } output.Write(");"); }
internal static void WriteEntity(this IPersistEntity entity, BinaryWriter entityWriter, ExpressMetaData metadata) { var expressType = metadata.ExpressType(entity); // entityWriter.Write(Convert.ToByte(P21ParseAction.NewEntity)); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var ifcProperty in expressType.Properties.Values) //only write out persistent attributes, ignore inverses { if (ifcProperty.EntityAttribute.State == EntityAttributeState.DerivedOverride) { entityWriter.Write(Convert.ToByte(P21ParseAction.SetOverrideValue)); } else { var propType = ifcProperty.PropertyInfo.PropertyType; var propVal = ifcProperty.PropertyInfo.GetValue(entity, null); WriteProperty(propType, propVal, entityWriter, metadata); } } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndEntity)); }
private void SetPropertyFromString(ExpressMetaProperty property, IPersistEntity entity, string value, int[] pos, Type valueType = null) { var pIndex = property.EntityAttribute.Order - 1; var type = valueType ?? property.PropertyInfo.PropertyType; type = GetNonNullableType(type); var propVal = new PropertyValue(); if (type.IsValueType || type == typeof(string)) { if (typeof(IExpressComplexType).IsAssignableFrom(type)) { var meta = _metadata.ExpressType(type); var values = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries); var underType = meta.UnderlyingComplexType; foreach (var v in values) { IPropertyValue pv; if (InitPropertyValue(underType, v, out pv)) { entity.Parse(pIndex, pv, pos); } } return; } if (type.IsEnum) { propVal.Init(value, StepParserType.Enum); entity.Parse(pIndex, propVal, pos); return; } //handle other value types if (typeof(IExpressValueType).IsAssignableFrom(type)) { var meta = _metadata.ExpressType(type); type = meta.UnderlyingType; } IPropertyValue pVal; if (InitPropertyValue(type, value, out pVal)) { entity.Parse(pIndex, pVal, pos); } 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) { throw new XbimParserException("Unexpected enumerable type " + type.Name); } var genType = type.GetGenericArguments()[0]; if (genType.IsValueType || genType == typeof(string)) { //handle enumerable of value type and string var values = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries); foreach (var v in values) { SetPropertyFromString(property, entity, v, pos, genType); } return; } //rectangular nested lists can also be serialized as attribute if defined in configuration if (typeof(IEnumerable).IsAssignableFrom(genType)) { //handle rectangular nested lists (like IfcPointList3D) var cardinality = property.EntityAttribute.MaxCardinality; if (cardinality != property.EntityAttribute.MinCardinality) { throw new XbimParserException(property.Name + " is not rectangular so it can't be serialized as a simple text string"); } var values = value.Split(_separator, StringSplitOptions.RemoveEmptyEntries); var valType = GetNonGenericType(genType); if (typeof(IExpressValueType).IsAssignableFrom(valType)) { var expValType = _metadata.ExpressType(valType); if (expValType == null) { throw new XbimParserException("Unexpected data type " + valType.Name); } valType = expValType.UnderlyingType; } for (var i = 0; i < values.Length; i++) { IPropertyValue pValue; InitPropertyValue(valType, values[i], out pValue); var idx = i / cardinality; entity.Parse(pIndex, pValue, new [] { idx }); } } }
private IPersistEntity ReadEntity(XmlReader input, Type suggestedType = null) { var expType = GetExpresType(input); if (expType == null && suggestedType != null && !suggestedType.IsAbstract) { expType = _metadata.ExpressType(suggestedType); } if (expType == null) { var typeName = input.GetAttribute("type") ?? input.LocalName; throw new XbimParserException(typeName + "is not an IPersistEntity type"); } var id = GetId(input, expType, out bool isRef); if (!id.HasValue) { throw new XbimParserException("Wrong entity XML format"); } var entity = _getOrCreate(id.Value, expType.Type); if (isRef) { if (!input.IsEmptyElement) { // Consume anything until the end of the entity. // this is usualy empty element but some people put data in there as well to indicate some of the // content for humans reading the XML (as much as it is silly) var depth = input.Depth; var hasContent = false; while (input.Read()) { if (input.NodeType == XmlNodeType.EndElement && input.Depth == depth) { break; } hasContent = true; } if (hasContent) { // Log a warning as it is a wrong practise to put content in ref elements Logger.LogWarning("Reference to element {0}, ref='{1}' is not empty. This is a wrong practise.", entity.ExpressType.Name, id); } } return(entity); } //read all attributes while (input.MoveToNextAttribute()) { var pInfo = GetMetaProperty(expType, input.LocalName); if (pInfo == null) { continue; } SetPropertyFromString(pInfo, entity, input.Value, null); } input.MoveToElement(); if (input.IsEmptyElement) { _finish(entity); return(entity); } //read all element properties var pDepth = input.Depth; while (input.Read()) { if (input.NodeType == XmlNodeType.EndElement && input.Depth == pDepth) { break; } if (input.NodeType != XmlNodeType.Element) { continue; } var pInfo = GetMetaProperty(expType, input.LocalName); if (pInfo == null) { continue; } SetPropertyFromElement(pInfo, entity, input, null); if (input.NodeType == XmlNodeType.EndElement && input.Depth == pDepth) { break; } } //finalize _finish(entity); return(entity); }
private static void WriteProperty(Type propType, object propVal, BinaryWriter entityWriter, ExpressMetaData metadata) { Type itemType; if (propVal == null) //null or a value type that maybe null { entityWriter.Write(Convert.ToByte(P21ParseAction.SetNonDefinedValue)); } else if (propVal is IOptionalItemSet && !((IOptionalItemSet)propVal).Initialized) { entityWriter.Write(Convert.ToByte(P21ParseAction.SetNonDefinedValue)); } else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable <>)) //deal with undefined types (nullables) { var complexType = propVal as IExpressComplexType; if (complexType != null) { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var compVal in complexType.Properties) { WriteProperty(compVal.GetType(), compVal, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if ((propVal is IExpressValueType)) { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, entityWriter); } else { WriteValueType(propVal.GetType(), propVal, entityWriter); } } else if (typeof(IExpressComplexType).IsAssignableFrom(propType)) { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var compVal in ((IExpressComplexType)propVal).Properties) { WriteProperty(compVal.GetType(), compVal, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if (typeof(IExpressValueType).IsAssignableFrom(propType)) //value types with a single property (IfcLabel, IfcInteger) { var realType = propVal.GetType(); if (realType != propType) //we have a type but it is a select type use the actual value but write out explicitly { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginNestedType)); entityWriter.Write(realType.Name.ToUpper()); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); WriteProperty(realType, propVal, entityWriter, metadata); entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndNestedType)); } else //need to write out underlying property value { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, entityWriter); } } else if (typeof(IExpressEnumerable).IsAssignableFrom(propType) && (itemType = propType.GetItemTypeFromGenericType()) != null) //only process lists that are real lists, see cartesianpoint { entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); foreach (var item in ((IExpressEnumerable)propVal)) { WriteProperty(itemType, item, entityWriter, metadata); } entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); } else if (typeof(IPersistEntity).IsAssignableFrom(propType)) //all writable entities must support this interface and ExpressType have been handled so only entities left { var val = ((IPersistEntity)propVal).EntityLabel; if (val <= UInt16.MaxValue) { entityWriter.Write((byte)P21ParseAction.SetObjectValueUInt16); entityWriter.Write(Convert.ToUInt16(val)); } else if (val <= Int32.MaxValue) { entityWriter.Write((byte)P21ParseAction.SetObjectValueInt32); entityWriter.Write(Convert.ToInt32(val)); } //else if (val <= Int64.MaxValue) //{ // //This is a very large model and it is unlikely we will be able to handle this number of entities, // //it is possible they have just created big labels and it needs to be renumbered // //Entity Label could be redfined as a long bu this is a large overhead if never required, let's see... // throw new XbimException("Entity Label is Init64, this is not currently supported"); // //entityWriter.Write((byte)P21ParseAction.SetObjectValueInt64); // //entityWriter.Write(val); //} else { throw new Exception("Entity Label exceeds maximim value for a an int32 long number"); } } else if (propType.IsValueType || propType == typeof(string)) //it might be an in-built value type double, string etc { WriteValueType(propVal.GetType(), propVal, entityWriter); } else if (typeof(IExpressSelectType).IsAssignableFrom(propType)) // a select type get the type of the actual value { if (propVal.GetType().IsValueType) //we have a value type, so write out explicitly { var type = metadata.ExpressType(propVal.GetType()); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginNestedType)); entityWriter.Write(type.ExpressNameUpper); entityWriter.Write(Convert.ToByte(P21ParseAction.BeginList)); WriteProperty(propVal.GetType(), propVal, entityWriter, metadata); entityWriter.Write(Convert.ToByte(P21ParseAction.EndList)); entityWriter.Write(Convert.ToByte(P21ParseAction.EndNestedType)); } else //could be anything so re-evaluate actual type { WriteProperty(propVal.GetType(), propVal, entityWriter, metadata); } } else { throw new Exception(string.Format("Entity has illegal property {0} of type {1}", propType.Name, propType.Name)); } }
internal static void WriteEntity(this IPersistEntity entity, TextWriter tw, byte[] propertyData, ExpressMetaData metadata) { var type = metadata.ExpressType(entity); tw.Write("#{0}={1}", entity.EntityLabel, type.ExpressNameUpper); var br = new BinaryReader(new MemoryStream(propertyData)); var action = (P21ParseAction)br.ReadByte(); var comma = false; //the first property while (action != P21ParseAction.EndEntity) { switch (action) { case P21ParseAction.BeginList: tw.Write("("); break; case P21ParseAction.EndList: tw.Write(")"); break; case P21ParseAction.BeginComplex: tw.Write("&SCOPE"); break; case P21ParseAction.EndComplex: tw.Write("ENDSCOPE"); break; case P21ParseAction.SetIntegerValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadInt64().ToString()); break; case P21ParseAction.SetHexValue: if (comma) { tw.Write(","); } comma = true; tw.Write(Convert.ToString(br.ReadInt64(), 16)); break; case P21ParseAction.SetFloatValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadDouble().AsPart21()); break; case P21ParseAction.SetStringValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadString()); break; case P21ParseAction.SetEnumValue: if (comma) { tw.Write(","); } comma = true; tw.Write("." + br.ReadString() + "."); break; case P21ParseAction.SetBooleanValue: if (comma) { tw.Write(","); } comma = true; tw.Write(br.ReadBoolean() ? ".T." : ".F."); break; case P21ParseAction.SetNonDefinedValue: if (comma) { tw.Write(","); } comma = true; tw.Write("$"); break; case P21ParseAction.SetOverrideValue: if (comma) { tw.Write(","); } comma = true; tw.Write("*"); break; case P21ParseAction.SetObjectValueUInt16: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadUInt16()); break; case P21ParseAction.SetObjectValueInt32: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadInt32()); break; case P21ParseAction.SetObjectValueInt64: if (comma) { tw.Write(","); } comma = true; tw.Write("#" + br.ReadInt64()); break; case P21ParseAction.BeginNestedType: if (comma) { tw.Write(","); } comma = false; tw.Write(br.ReadString() + "("); break; case P21ParseAction.EndNestedType: comma = true; tw.Write(")"); break; case P21ParseAction.EndEntity: tw.Write(");"); break; case P21ParseAction.NewEntity: comma = false; tw.Write("("); break; default: throw new Exception("Invalid Property Record #" + entity.EntityLabel + " EntityType: " + entity.GetType().Name); } action = (P21ParseAction)br.ReadByte(); } tw.WriteLine(); }
/// <summary> /// Writes a property of an entity to the TextWriter in the Part21 format /// </summary> /// <param name="propType"></param> /// <param name="propVal"></param> /// <param name="output"></param> /// <param name="map"></param> /// <param name="metadata"></param> public static void WriteProperty(Type propType, object propVal, TextWriter output, IDictionary <int, int> map, ExpressMetaData metadata) { Type itemType; if (propVal == null) //null or a value type that maybe null { output.Write('$'); } else if (propVal is IOptionalItemSet && !((IOptionalItemSet)propVal).Initialized) { output.Write('$'); } else if (propType.GetTypeInfo().IsGenericType&& propType.GetGenericTypeDefinition() == typeof(Nullable <>)) //deal with undefined types (nullables) { var complexType = propVal as IExpressComplexType; if (complexType != null) { output.Write('('); var first = true; foreach (var compVal in complexType.Properties) { if (!first) { output.Write(','); } WriteProperty(compVal.GetType(), compVal, output, map, metadata); first = false; } output.Write(')'); } else if ((propVal is IExpressValueType)) { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, output); } else // if (propVal.GetType().IsEnum) { WriteValueType(propVal.GetType(), propVal, output); } } else if (typeof(IExpressComplexType).GetTypeInfo().IsAssignableFrom(propType)) { output.Write('('); var first = true; foreach (var compVal in ((IExpressComplexType)propVal).Properties) { if (!first) { output.Write(','); } WriteProperty(compVal.GetType(), compVal, output, map, metadata); first = false; } output.Write(')'); } else if (typeof(IExpressValueType).GetTypeInfo().IsAssignableFrom(propType)) //value types with a single property (IfcLabel, IfcInteger) { var realType = propVal.GetType(); if (realType != propType) //we have a type but it is a select type use the actual value but write out explicitly { output.Write(realType.Name.ToUpper()); output.Write('('); WriteProperty(realType, propVal, output, map, metadata); output.Write(')'); } else //need to write out underlying property value { var expressVal = (IExpressValueType)propVal; WriteValueType(expressVal.UnderlyingSystemType, expressVal.Value, output); } } else if (typeof(IExpressEnumerable).GetTypeInfo().IsAssignableFrom(propType) && (itemType = propType.GetItemTypeFromGenericType()) != null) //only process lists that are real lists, see Cartesian point { output.Write('('); var first = true; foreach (var item in ((IExpressEnumerable)propVal)) { if (!first) { output.Write(','); } WriteProperty(itemType, item, output, map, metadata); first = false; } output.Write(')'); } else if (typeof(IPersistEntity).GetTypeInfo().IsAssignableFrom(propType)) //all writable entities must support this interface and ExpressType have been handled so only entities left { output.Write('#'); var label = ((IPersistEntity)propVal).EntityLabel; int mapLabel; if (map != null && map.TryGetValue(label, out mapLabel)) { label = mapLabel; } output.Write(label); } else if (propType.GetTypeInfo().IsValueType || propVal is string || propVal is byte[]) //it might be an in-built value type double, string etc. { WriteValueType(propVal.GetType(), propVal, output); } else if (typeof(IExpressSelectType).GetTypeInfo().IsAssignableFrom(propType)) // a select type get the type of the actual value { if (propVal.GetType().GetTypeInfo().IsValueType) //we have a value type, so write out explicitly { var type = metadata.ExpressType(propVal.GetType()); output.Write(type.ExpressNameUpper); output.Write('('); WriteProperty(propVal.GetType(), propVal, output, map, metadata); output.Write(')'); } else //could be anything so re-evaluate actual type { WriteProperty(propVal.GetType(), propVal, output, map, metadata); } } else { throw new Exception(string.Format("Entity has illegal property {0} of type {1}", propType.Name, propType.Name)); } }
public ExpressType Resolve(ExpressType abstractType, ReferenceContext context, ExpressMetaData metaData) { return(metaData.ExpressType(typeof(StringValue))); }