internal virtual void SerializeInternal(EdiWriter writer, object value, Type objectType) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } if (value == null) { writer.WriteNull(); return; } objectType = objectType ?? value.GetType(); var stack = new Stack <EdiStructure>(); // If this is not a collection type asume this type is the interchange. if (!objectType.IsCollectionType()) { stack.Push(new EdiStructure(EdiStructureType.Interchange, value)); if (writer.WriteState == WriteState.Start) { writer.WriteServiceStringAdvice(); } SerializeStructure(writer, stack); } // else if this is indeed a collection type this must be a collection of messages. else { throw new NotImplementedException("Collection types are not supported as the root Type. Try to wrap List of Messages inside a container type."); } }
private static void SerializeStructure(EdiWriter writer, Stack <EdiStructure> stack, EdiPathComparer structuralComparer = null) { structuralComparer = structuralComparer ?? new EdiPathComparer(writer.Grammar); var structure = stack.Peek(); var properies = structure.GetOrderedProperties(structuralComparer); foreach (var property in properies) { var value = property.Info.GetValue(structure.Instance); if (property.ValueInfo != null) { var path = (EdiPath)writer.Path; var propertyPath = property.PathInfo.PathInternal; var container = stack.Skip(1).FirstOrDefault(); if (propertyPath.Segment.IsWildcard) { if (container.Descriptor.Path.HasValue && !container.Descriptor.Path.Value.Segment.IsWildcard) { propertyPath = new EdiPath(container.Descriptor.Path.Value.Segment, propertyPath.Element, propertyPath.Component); } } if (propertyPath.Element.IsWildcard) { propertyPath = new EdiPath(propertyPath.Segment, new EdiPathFragment(structure.Index.ToString()), propertyPath.Component); } if (path.Segment != propertyPath.Segment || structuralComparer.Compare(path, propertyPath) > 0) { writer.WriteSegmentName(propertyPath.Segment); path = (EdiPath)writer.Path; } // the following loop handles the write of unmapped preceding elements/components to the one being writen // so that path progression stays intact even though we do not have all properties present on the model. while (structuralComparer.Compare(path, propertyPath) < 0) { if (!path.Element.Equals(propertyPath.Element)) { if (path.ElementIndex == 0 && writer.WriteState != WriteState.Component && writer.WriteState != WriteState.Element) { writer.WriteToken(EdiToken.Null); } else { writer.WriteToken(EdiToken.ElementStart); } } else if (!path.Component.Equals(propertyPath.Component)) { if (path.ComponentIndex == 0 && writer.WriteState != WriteState.Component) { writer.WriteToken(EdiToken.Null); } else { writer.WriteToken(EdiToken.ComponentStart); } } path = (EdiPath)writer.Path; } // handle auto generated values. if (property.AutoGenerationInfo != null) { // do stuff. // there should be plenty of things to work with inside the EdiWriter itself. // We are already keeping keeping track of current position with an index. // But it may need to track more stuff in order for this to happen. } writer.WriteValue(value, property.ValueInfo.Picture, property.ValueInfo.Format); } else { // this is somekind of structure. Group/Message/Segment/SegmentGroup/Element // is it a collection of some kind? var container = property.Attributes.InferStructure(); if (property.Info.PropertyType.IsCollectionType()) { var itemType = default(Type); var collection = (value ?? new object[0]) as IList; if (property.Info.PropertyType.IsArray) { itemType = property.Info.PropertyType.GetElementType(); } else { itemType = property.Info.PropertyType.GetGenericArguments().First(); } for (var i = 0; i < collection.Count; i++) { var item = collection[i]; if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {itemType.Name}"); } while (stack.Peek().StructureType >= container) { var previous = stack.Pop(); } stack.Push(new EdiStructure(container, stack.Peek(), property, item, i, null)); SerializeStructure(writer, stack, structuralComparer); } } else { // or a simple Container. if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {property.Info.PropertyType.Name}"); } while (stack.Peek().StructureType >= container) { var previous = stack.Pop(); } if (value == null) { continue; } stack.Push(new EdiStructure(container, stack.Peek(), property, value)); SerializeStructure(writer, stack, structuralComparer); } } } }
/// <summary> /// Serializes the specified <see cref="object"/> and writes the EDI structure /// to a <c>Stream</c> using the specified <see cref="EdiWriter"/>. /// </summary> /// <param name="ediWriter">The <see cref="EdiWriter"/> used to write the EDI structure.</param> /// <param name="value">The <see cref="object"/> to serialize.</param> /// <param name="objectType"> /// The type of the value being serialized. /// Specifing the type is optional. /// </param> public void Serialize(EdiWriter ediWriter, object value, Type objectType) { ediWriter.EnableCompression = EnableCompression; SerializeInternal(ediWriter, value, objectType); ediWriter.Close(); }
/// <summary> /// Serializes the specified <see cref="Object"/> and writes the EDI structure /// to a <c>Stream</c> using the specified <see cref="EdiWriter"/>. /// </summary> /// <param name="ediWriter">The <see cref="EdiWriter"/> used to write the EDI structure.</param> /// <param name="value">The <see cref="Object"/> to serialize.</param> /// <param name="objectType"> /// The type of the value being serialized. /// Specifing the type is optional. /// </param> public void Serialize(EdiWriter ediWriter, object value, Type objectType) { SerializeInternal(ediWriter, value, objectType); }
/// <summary> /// Serializes the structure. /// </summary> /// <param name="writer">Writer.</param> /// <param name="stack">Stack.</param> /// <param name="structuralComparer">Structural comparer.</param> private static void SerializeStructure(EdiWriter writer, Stack <EdiStructure> stack, EdiPathComparer structuralComparer = null) { structuralComparer = structuralComparer ?? new EdiPathComparer(writer.Grammar); var structure = stack.Peek(); var properies = structure.GetOrderedProperties(structuralComparer); foreach (var property in properies) { var value = property.Info.GetValue(structure.Instance); if (property.ValueInfo != null) { var path = (EdiPath)writer.Path; if (path.Segment != property.PathInfo.Segment || structuralComparer.Compare(path, property.PathInfo.PathInternal) > 0) { writer.WriteSegmentName(property.PathInfo.Segment); } while (structuralComparer.Compare(path, property.PathInfo.PathInternal) < 0) { path = (EdiPath)writer.Path; if (path.ElementIndex != property.PathInfo.ElementIndex) { writer.WriteToken(EdiToken.ElementStart); } else if (path.ComponentIndex != property.PathInfo.ComponentIndex) { writer.WriteToken(EdiToken.ComponentStart); } } writer.WriteValue(value, property.ValueInfo.Picture, property.ValueInfo.Format); } else { // this is somekind of structure. Group/Message/Segment/SegmentGroup/Element // is it a collection of some kind? var container = property.Attributes.InferStructure(); if (property.Info.PropertyType.IsCollectionType()) { var itemType = default(Type); var collection = (value ?? new object[0]) as IList; if (property.Info.PropertyType.IsArray) { itemType = property.Info.PropertyType.GetElementType(); } else { itemType = property.Info.PropertyType.GetGenericArguments().First(); } for (var i = 0; i < collection.Count; i++) { var item = collection[i]; if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {itemType.Name}"); } while (stack.Peek().Container >= container) { var previous = stack.Pop(); } stack.Push(new EdiStructure(container, item, i, null)); SerializeStructure(writer, stack, structuralComparer); } } else { // or a simple Container. if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {property.Info.PropertyType.Name}"); } while (stack.Peek().Container >= container) { var previous = stack.Pop(); } if (value == null) { continue; } stack.Push(new EdiStructure(container, value)); SerializeStructure(writer, stack, structuralComparer); } } } }
/// <summary> /// Serializes the specified <see cref="object"/> and writes the EDI structure /// to a <c>Stream</c> using the specified <see cref="EdiWriter"/>. /// </summary> /// <param name="ediWriter">The <see cref="EdiWriter"/> used to write the EDI structure.</param> /// <param name="value">The <see cref="object"/> to serialize.</param> public void Serialize(EdiWriter ediWriter, object value) { ediWriter.EnableCompression = EnableCompression; SerializeInternal(ediWriter, value, null); }
/// <summary> /// Serializes the specified <see cref="Object"/> and writes the EDI structure /// to a <c>Stream</c> using the specified <see cref="EdiWriter"/>. /// </summary> /// <param name="ediWriter">The <see cref="EdiWriter"/> used to write the EDI structure.</param> /// <param name="value">The <see cref="Object"/> to serialize.</param> public void Serialize(EdiWriter ediWriter, object value) { SerializeInternal(ediWriter, value, null); }
internal static void WriteValue(EdiWriter writer, PrimitiveTypeCode typeCode, object value, Picture? picture, string format) { switch (typeCode) { case PrimitiveTypeCode.Char: writer.WriteValue((char)value); break; case PrimitiveTypeCode.CharNullable: writer.WriteValue((value == null) ? (char?)null : (char)value); break; case PrimitiveTypeCode.Boolean: writer.WriteValue((bool)value); break; case PrimitiveTypeCode.BooleanNullable: writer.WriteValue((value == null) ? (bool?)null : (bool)value); break; case PrimitiveTypeCode.SByte: writer.WriteValue((sbyte)value, picture); break; case PrimitiveTypeCode.SByteNullable: writer.WriteValue((value == null) ? (sbyte?)null : (sbyte)value, picture); break; case PrimitiveTypeCode.Int16: writer.WriteValue((short)value, picture); break; case PrimitiveTypeCode.Int16Nullable: writer.WriteValue((value == null) ? (short?)null : (short)value, picture); break; case PrimitiveTypeCode.UInt16: writer.WriteValue((ushort)value, picture); break; case PrimitiveTypeCode.UInt16Nullable: writer.WriteValue((value == null) ? (ushort?)null : (ushort)value, picture); break; case PrimitiveTypeCode.Int32: writer.WriteValue((int)value, picture); break; case PrimitiveTypeCode.Int32Nullable: writer.WriteValue((value == null) ? (int?)null : (int)value, picture); break; case PrimitiveTypeCode.Byte: writer.WriteValue((byte)value, picture); break; case PrimitiveTypeCode.ByteNullable: writer.WriteValue((value == null) ? (byte?)null : (byte)value, picture); break; case PrimitiveTypeCode.UInt32: writer.WriteValue((uint)value, picture); break; case PrimitiveTypeCode.UInt32Nullable: writer.WriteValue((value == null) ? (uint?)null : (uint)value); break; case PrimitiveTypeCode.Int64: writer.WriteValue((long)value, picture); break; case PrimitiveTypeCode.Int64Nullable: writer.WriteValue((value == null) ? (long?)null : (long)value, picture); break; case PrimitiveTypeCode.UInt64: writer.WriteValue((ulong)value, picture); break; case PrimitiveTypeCode.UInt64Nullable: writer.WriteValue((value == null) ? (ulong?)null : (ulong)value, picture); break; case PrimitiveTypeCode.Single: writer.WriteValue((float)value, picture); break; case PrimitiveTypeCode.SingleNullable: writer.WriteValue((value == null) ? (float?)null : (float)value); break; case PrimitiveTypeCode.Double: writer.WriteValue((double)value, picture); break; case PrimitiveTypeCode.DoubleNullable: writer.WriteValue((value == null) ? (double?)null : (double)value, picture); break; case PrimitiveTypeCode.DateTime: writer.WriteValue((DateTime)value, format); break; case PrimitiveTypeCode.DateTimeNullable: writer.WriteValue((value == null) ? (DateTime?)null : (DateTime)value, format); break; case PrimitiveTypeCode.DateTimeOffset: writer.WriteValue((DateTimeOffset)value, format); break; case PrimitiveTypeCode.DateTimeOffsetNullable: writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value, format); break; case PrimitiveTypeCode.Decimal: writer.WriteValue((decimal)value, picture); break; case PrimitiveTypeCode.DecimalNullable: writer.WriteValue((value == null) ? (decimal?)null : (decimal)value, picture); break; case PrimitiveTypeCode.Guid: writer.WriteValue((Guid)value); break; case PrimitiveTypeCode.GuidNullable: writer.WriteValue((value == null) ? (Guid?)null : (Guid)value); break; case PrimitiveTypeCode.TimeSpan: writer.WriteValue((TimeSpan)value); break; case PrimitiveTypeCode.TimeSpanNullable: writer.WriteValue((value == null) ? (TimeSpan?)null : (TimeSpan)value); break; #if !PORTABLE case PrimitiveTypeCode.BigInteger: // this will call to WriteValue(object) writer.WriteValue((BigInteger)value); break; case PrimitiveTypeCode.BigIntegerNullable: // this will call to WriteValue(object) writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value); break; #endif case PrimitiveTypeCode.Uri: writer.WriteValue((Uri)value); break; case PrimitiveTypeCode.String: writer.WriteValue((string)value, picture); break; case PrimitiveTypeCode.Bytes: writer.WriteValue((byte[])value); break; #if !(PORTABLE || DOTNET) case PrimitiveTypeCode.DBNull: writer.WriteNull(); break; #endif default: #if !PORTABLE if (value is IConvertible) { // the value is a non-standard IConvertible // convert to the underlying value and retry IConvertible convertable = (IConvertible)value; TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable); // if convertable has an underlying typecode of Object then attempt to convert it to a string PrimitiveTypeCode resolvedTypeCode = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode; Type resolvedType = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type; object convertedValue = convertable.ToType(resolvedType, CultureInfo.InvariantCulture); WriteValue(writer, resolvedTypeCode, convertedValue, picture, format); break; } else #endif { WriteValue(writer, PrimitiveTypeCode.String, $"{value}", picture, format); break; // consider throwing some times... //throw CreateUnsupportedTypeException(writer, value); } } }
internal static EdiWriterException Create(EdiWriter writer, string message, Exception ex) { return Create(writer.ContainerPath, message, ex); }
private static EdiWriterException CreateUnsupportedTypeException(EdiWriter writer, object value) { return EdiWriterException.Create(writer, "Unsupported type: {0}. Use the EdiSerializer class to get the object's EDI representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); }
/// <summary> /// Create the specified writer, message and ex. /// </summary> /// <param name="writer">Writer.</param> /// <param name="message">Message.</param> /// <param name="ex">Ex.</param> internal static EdiWriterException Create(EdiWriter writer, string message, Exception ex) { return(Create(writer.ContainerPath, message, ex)); }
private static void SerializeStructure(EdiWriter writer, Stack <EdiStructure> stack, EdiPathComparer structuralComparer = null) { structuralComparer = structuralComparer ?? new EdiPathComparer(writer.Grammar); var structure = stack.Peek(); var properies = structure.GetOrderedProperties(structuralComparer); foreach (var property in properies) { var value = property.Info.GetValue(structure.Instance); if (property.ValueInfo != null) { var path = (EdiPath)writer.Path; if (path.Segment != property.PathInfo.Segment || structuralComparer.Compare(path, property.PathInfo.PathInternal) > 0) { writer.WriteSegmentName(property.PathInfo.Segment); path = (EdiPath)writer.Path; } // the following loop handles the write of unmapped preceding elements/components to the one being writen // so that path progression stays intact even though we do not have all properties present on the model. // TODO: Potentialy this is related to compression. while (structuralComparer.Compare(path, property.PathInfo.PathInternal) < 0) { path = (EdiPath)writer.Path; if (path.ElementIndex == 0 && writer.WriteState != WriteState.Component && writer.WriteState != WriteState.Element) { writer.WriteToken(EdiToken.Null); } else if (path.ElementIndex != property.PathInfo.ElementIndex) { writer.WriteToken(EdiToken.ElementStart); } else if (path.ComponentIndex == 0 && writer.WriteState != WriteState.Component && writer.WriteState != WriteState.Element) { writer.WriteToken(EdiToken.Null); } else if (path.ComponentIndex != property.PathInfo.ComponentIndex) { writer.WriteToken(EdiToken.ComponentStart); } } writer.WriteValue(value, property.ValueInfo.Picture, property.ValueInfo.Format); } else { // this is somekind of structure. Group/Message/Segment/SegmentGroup/Element // is it a collection of some kind? var container = property.Attributes.InferStructure(); if (property.Info.PropertyType.IsCollectionType()) { var itemType = default(Type); var collection = (value ?? new object[0]) as IList; if (property.Info.PropertyType.IsArray) { itemType = property.Info.PropertyType.GetElementType(); } else { itemType = property.Info.PropertyType.GetGenericArguments().First(); } for (var i = 0; i < collection.Count; i++) { var item = collection[i]; if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {itemType.Name}"); } while (stack.Peek().StructureType >= container) { var previous = stack.Pop(); } stack.Push(new EdiStructure(container, stack.Peek(), property, item, i, null)); SerializeStructure(writer, stack, structuralComparer); } } else { // or a simple Container. if (stack.Count == 0) { throw new EdiException($"Serialization stack empty while in the middle of proccessing a collection of {property.Info.PropertyType.Name}"); } while (stack.Peek().StructureType >= container) { var previous = stack.Pop(); } if (value == null) { continue; } stack.Push(new EdiStructure(container, stack.Peek(), property, value)); SerializeStructure(writer, stack, structuralComparer); } } } }
private static EdiWriterException CreateUnsupportedTypeException(EdiWriter writer, object value) { return(EdiWriterException.Create(writer, "Unsupported type: {0}. Use the EdiSerializer class to get the object's EDI representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null)); }
internal static void WriteValue(EdiWriter writer, PrimitiveTypeCode typeCode, object value, Picture?picture, string format) { switch (typeCode) { case PrimitiveTypeCode.Char: writer.WriteValue((char)value); break; case PrimitiveTypeCode.CharNullable: writer.WriteValue((value == null) ? (char?)null : (char)value); break; case PrimitiveTypeCode.Boolean: writer.WriteValue((bool)value); break; case PrimitiveTypeCode.BooleanNullable: writer.WriteValue((value == null) ? (bool?)null : (bool)value); break; case PrimitiveTypeCode.SByte: writer.WriteValue((sbyte)value, picture); break; case PrimitiveTypeCode.SByteNullable: writer.WriteValue((value == null) ? (sbyte?)null : (sbyte)value, picture); break; case PrimitiveTypeCode.Int16: writer.WriteValue((short)value, picture); break; case PrimitiveTypeCode.Int16Nullable: writer.WriteValue((value == null) ? (short?)null : (short)value, picture); break; case PrimitiveTypeCode.UInt16: writer.WriteValue((ushort)value, picture); break; case PrimitiveTypeCode.UInt16Nullable: writer.WriteValue((value == null) ? (ushort?)null : (ushort)value, picture); break; case PrimitiveTypeCode.Int32: writer.WriteValue((int)value, picture); break; case PrimitiveTypeCode.Int32Nullable: writer.WriteValue((value == null) ? (int?)null : (int)value, picture); break; case PrimitiveTypeCode.Byte: writer.WriteValue((byte)value, picture); break; case PrimitiveTypeCode.ByteNullable: writer.WriteValue((value == null) ? (byte?)null : (byte)value, picture); break; case PrimitiveTypeCode.UInt32: writer.WriteValue((uint)value, picture); break; case PrimitiveTypeCode.UInt32Nullable: writer.WriteValue((value == null) ? (uint?)null : (uint)value); break; case PrimitiveTypeCode.Int64: writer.WriteValue((long)value, picture); break; case PrimitiveTypeCode.Int64Nullable: writer.WriteValue((value == null) ? (long?)null : (long)value, picture); break; case PrimitiveTypeCode.UInt64: writer.WriteValue((ulong)value, picture); break; case PrimitiveTypeCode.UInt64Nullable: writer.WriteValue((value == null) ? (ulong?)null : (ulong)value, picture); break; case PrimitiveTypeCode.Single: writer.WriteValue((float)value, picture); break; case PrimitiveTypeCode.SingleNullable: writer.WriteValue((value == null) ? (float?)null : (float)value); break; case PrimitiveTypeCode.Double: writer.WriteValue((double)value, picture); break; case PrimitiveTypeCode.DoubleNullable: writer.WriteValue((value == null) ? (double?)null : (double)value, picture); break; case PrimitiveTypeCode.DateTime: writer.WriteValue((DateTime)value, format); break; case PrimitiveTypeCode.DateTimeNullable: writer.WriteValue((value == null) ? (DateTime?)null : (DateTime)value, format); break; case PrimitiveTypeCode.DateTimeOffset: writer.WriteValue((DateTimeOffset)value, format); break; case PrimitiveTypeCode.DateTimeOffsetNullable: writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value, format); break; case PrimitiveTypeCode.Decimal: writer.WriteValue((decimal)value, picture); break; case PrimitiveTypeCode.DecimalNullable: writer.WriteValue((value == null) ? (decimal?)null : (decimal)value, picture); break; case PrimitiveTypeCode.Guid: writer.WriteValue((Guid)value); break; case PrimitiveTypeCode.GuidNullable: writer.WriteValue((value == null) ? (Guid?)null : (Guid)value); break; case PrimitiveTypeCode.TimeSpan: writer.WriteValue((TimeSpan)value); break; case PrimitiveTypeCode.TimeSpanNullable: writer.WriteValue((value == null) ? (TimeSpan?)null : (TimeSpan)value); break; #if !PORTABLE case PrimitiveTypeCode.BigInteger: // this will call to WriteValue(object) writer.WriteValue((BigInteger)value); break; case PrimitiveTypeCode.BigIntegerNullable: // this will call to WriteValue(object) writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value); break; #endif case PrimitiveTypeCode.Uri: writer.WriteValue((Uri)value); break; case PrimitiveTypeCode.String: writer.WriteValue((string)value, picture); break; case PrimitiveTypeCode.Bytes: writer.WriteValue((byte[])value); break; #if !(PORTABLE || DOTNET) case PrimitiveTypeCode.DBNull: writer.WriteNull(); break; #endif default: #if !PORTABLE if (value is IConvertible) { // the value is a non-standard IConvertible // convert to the underlying value and retry IConvertible convertable = (IConvertible)value; TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable); // if convertable has an underlying typecode of Object then attempt to convert it to a string PrimitiveTypeCode resolvedTypeCode = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode; Type resolvedType = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type; object convertedValue = convertable.ToType(resolvedType, CultureInfo.InvariantCulture); WriteValue(writer, resolvedTypeCode, convertedValue, picture, format); break; } else #endif { WriteValue(writer, PrimitiveTypeCode.String, $"{value}", picture, format); break; // consider throwing some times... //throw CreateUnsupportedTypeException(writer, value); } } }