/// <summary> /// Retrieves all IsoField Attributes and Properties of TMessage Class /// </summary> /// <typeparam name="TMessage">TMessage</typeparam> /// <param name="messageType">message type</param> /// <returns>A Dictionary of TMessage Properties and IsoField Attributes of TMessage Class</returns> internal static Dictionary <PropertyInfo, IsoFieldAttribute> PropsAndIsoFieldAttributes <TMessage>(this Type messageType) where TMessage : BaseMessage { #if NET40 IEnumerable <PropertyInfo> isoFieldProps = messageType?.GetProperties().Where( prop => Attribute.GetCustomAttributes(prop).Any(attr => attr.GetType() == typeof(IsoFieldAttribute))); #else IEnumerable <PropertyInfo> isoFieldProps = messageType?.GetProperties().Where( prop => prop.GetCustomAttributes().Any(attr => attr.GetType() == typeof(IsoFieldAttribute))); #endif if (!isoFieldProps.Any()) { throw new ArgumentException($"for type {messageType?.FullName} they have not been defined any properties with attibute of IsoFieldAttribute"); } var isoAPropsttributesOfT = new Dictionary <PropertyInfo, IsoFieldAttribute>(); foreach (PropertyInfo isoFieldProp in isoFieldProps) { #if NET40 IsoFieldAttribute isoFieldFieldAttr = (IsoFieldAttribute)Attribute.GetCustomAttribute(isoFieldProp, typeof(IsoFieldAttribute)); #else IsoFieldAttribute isoFieldFieldAttr = isoFieldProp.GetCustomAttribute <IsoFieldAttribute>(); #endif isoAPropsttributesOfT.Add(isoFieldProp, isoFieldFieldAttr); } return(isoAPropsttributesOfT); }
/// <summary> /// Gets Custom Field Len according to Len Bytes /// </summary> /// <param name="isoFieldAttribute">iso Field Attribute</param> /// <param name="isoMessageBytes">iso message bytes</param> /// <param name="currentPos">current parsing position</param> /// <returns>length of Custom Field parsed</returns> internal static int TagFieldLength(this IsoFieldAttribute isoFieldAttribute, byte[] isoMessageBytes, ref int currentPos) { var fieldLen = 0; var fieldValue = string.Empty; var lengthBytes = (int)isoFieldAttribute.LengthType; if (isoFieldAttribute.LenDataType == DataType.ASCII) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldAttribute.Encoding); fieldLen = int.Parse(lenValue); } else if (isoFieldAttribute.LenDataType == DataType.HEX) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldAttribute.Encoding); fieldLen = lenValue.HexValueToInt(); } else if (isoFieldAttribute.LenDataType == DataType.BCD) { lengthBytes = lengthBytes - 1; var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToArray().BDCToString(); fieldLen = int.Parse(lenValue); } currentPos = currentPos + lengthBytes; return(fieldLen); }
/// <summary> /// Parse BitMap of Message to be Parsed /// </summary> /// <typeparam name="TMessage">TMessage class, a derived class of BaseMessage class</typeparam> /// <param name="message">message instance</param> /// <param name="isoMessageBytes">messageBytes</param> /// <param name="currentPos">position to Read</param> /// <returns>BitMap Value</returns> private string ParseBitMap <TMessage>(TMessage message, byte[] isoMessageBytes, ref int currentPos) where TMessage : BaseMessage, new() { IsoFieldAttribute bitMapIsoField = message.GetIsoFieldByPropName(nameof(BaseMessage.BitMap)); var bitMap = bitMapIsoField.GetFieldValue(isoMessageBytes, ref currentPos); //Second BitMap Exists Read More Data if (bitMap.ToBinaryStringFromHex().First() == '1') { return(bitMap + bitMapIsoField.GetFieldValue(isoMessageBytes, ref currentPos)); } return(bitMap); }
/// <summary> /// Parse a byte[] iso Message to an Instance of TMessage /// </summary> /// <typeparam name="TMessage">TMessage class, a derived class of BaseMessage class</typeparam> /// <param name="isoMessageBytes">bytes of received Message</param> /// <returns>an Instance of TMessage</returns> public TMessage Parse <TMessage>(byte[] isoMessageBytes) where TMessage : BaseMessage, new() { var currentPosition = 0; var messageIntance = new TMessage(); IsoFieldAttribute mtiIsoField = messageIntance.GetIsoFieldByPropName(nameof(messageIntance.MTI)); messageIntance.MTI = mtiIsoField.GetFieldValue(isoMessageBytes, ref currentPosition); messageIntance.BitMap = ParseBitMap(messageIntance, isoMessageBytes, ref currentPosition); ParseFields(ref messageIntance, isoMessageBytes, currentPosition); return(messageIntance); }
/// <summary> /// Builds Byte[] from Instance of Message /// </summary> /// <typeparam name="TMessage">TMessage class, a derived class of BaseMessage class</typeparam> /// <param name="message">message instance</param> /// <param name="MTI">MTI Response value</param> /// <param name="notIncludeFields">whether the BitMap will Contain Fields without values</param> /// <returns>byte array Iso Message</returns> public byte[] Build <TMessage>(TMessage message, string MTI, params IsoFields[] notIncludeFields) where TMessage : BaseMessage, new() { IEnumerable <int> orderedFieldPositions = message.MessagePropsIsoFieldAttributes.Select(c => (int)c.Value.Position); IsoFieldAttribute mtiIsoField = message.GetIsoFieldByPropName(nameof(message.MTI)); var mtiBytes = mtiIsoField.BuildFieldValue(MTI); var messageBytes = new List <byte>(mtiBytes); IEnumerable <int> fieldsForBitMap = orderedFieldPositions.Where(pos => !notIncludeFields.Contains((IsoFields)pos)); messageBytes.AddRange(BuildBitMap(message, fieldsForBitMap)); IEnumerable <int> fieldsToBuild = fieldsForBitMap.Where(pos => pos != (int)IsoFields.F1 && pos != (int)IsoFields.BitMap && pos != (int)IsoFields.MTI); BuildFields(fieldsToBuild, message, ref messageBytes); return(messageBytes.ToArray()); }
private IEnumerable <byte> BuildTagFields(CustomField valueForMessage, IsoFieldAttribute propAttr) { var customFieldBytes = new List <byte>(); foreach ((PropertyInfo propInfo, TagAttribute propTagAttr) in valueForMessage.TagPropsIsoFieldAttributes) { var tagFieldValue = GetValueFromInstance(valueForMessage, propInfo); if (tagFieldValue == null) { continue; } customFieldBytes.AddRange(propTagAttr.GetTagBytes(tagFieldValue.ToString())); } return(customFieldBytes); }
internal static byte[] BuildCustomFieldLentgh(this IsoFieldAttribute isoFieldAttribute, string lenValue) { lenValue = lenValue.PadLeft((int)isoFieldAttribute.LengthType, '0'); switch (isoFieldAttribute.LenDataType) { case DataType.ASCII: return(lenValue.FromASCIIToBytes(isoFieldAttribute.Encoding)); case DataType.HEX: var intLen = int.Parse(lenValue); return(intLen.IntToHexValue((int)isoFieldAttribute.LengthType).FromASCIIToBytes(isoFieldAttribute.Encoding)); case DataType.BCD: return(lenValue.ConvertToBinaryCodedDecimal(false, (int)isoFieldAttribute.LengthType - 1)); default: throw new BuildFieldException(isoFieldAttribute, $"Cannot Parse Length value for {isoFieldAttribute?.Position} and Len Type {isoFieldAttribute?.LenDataType}"); } }
/// <summary> /// Builds BitMap value of Message to Send /// </summary> /// <typeparam name="TMessage">TMessage class, a derived class of BaseMessage class</typeparam> /// <param name="message">message instance</param> /// <param name="orderedFields">ordered fields positions</param> /// <returns>byte array bitMap value</returns> private byte[] BuildBitMap <TMessage>(TMessage message, IEnumerable <int> orderedFields) where TMessage : BaseMessage, new() { var secondBitRequired = orderedFields.Any(pos => pos > 65 && pos < 128); IsoFieldAttribute bitMapIsoField = message.GetIsoFieldByPropName(nameof(BaseMessage.BitMap)); char[] bitmapBinaryArray = null; if (secondBitRequired) { bitmapBinaryArray = new char[129]; bitmapBinaryArray[1] = '1'; } else { bitmapBinaryArray = new char[65]; bitmapBinaryArray[1] = '0'; } //Building BitMap for (var i = 2; i < bitmapBinaryArray.Length; i++) { if (orderedFields.Contains(i)) { bitmapBinaryArray[i] = '1'; } else { bitmapBinaryArray[i] = '0'; } } var bitmapString = new string(bitmapBinaryArray); var bitMap = Convert.ToInt64(bitmapString.Substring(1, 64), 2).ToString("X").PadLeft(16, '0'); if (secondBitRequired) { bitMap = bitMap + Convert.ToInt64(bitmapString.Substring(65, 64), 2).ToString("X").PadLeft(16, '0'); } return(bitMapIsoField.BuildFieldValue(bitMap)); }
/// <summary> /// Build Bytes from Field Value /// </summary> /// <param name="isoFieldAttribute">isofield attribute of Property</param> /// <param name="fieldValue">field value</param> /// <returns>byte array value of Field</returns> internal static byte[] BuildFieldValue(this IsoFieldAttribute isoFieldAttribute, string fieldValue) { var fieldBytes = new List <byte>(); try { switch (isoFieldAttribute.LengthType) { case LengthType.FIXED: if (fieldValue.Length < isoFieldAttribute.MaxLen) { fieldValue = fieldValue?.PadRight(isoFieldAttribute.MaxLen); } break; case LengthType.LVAR: case LengthType.LLVAR: case LengthType.LLLVAR: if (isoFieldAttribute.LenDataType == DataType.ASCII) { var valueLen = fieldValue?.Length.ToString().PadLeft((int)isoFieldAttribute.LengthType, '0'); fieldBytes.AddRange(valueLen.FromASCIIToBytes(isoFieldAttribute.Encoding)); } else if (isoFieldAttribute.LenDataType == DataType.HEX) { var valueLen = fieldValue?.Length.IntToHexValue((int)isoFieldAttribute.LengthType); fieldBytes.AddRange(valueLen.FromASCIIToBytes(isoFieldAttribute.Encoding)); } else if (isoFieldAttribute.LenDataType == DataType.BCD) { var valueLen = fieldValue?.Length.ToString().ConvertToBinaryCodedDecimal(false); fieldBytes.AddRange(valueLen); } break; default: throw new BuildFieldException(isoFieldAttribute, $"Cannot Parse Length value for {isoFieldAttribute?.Position} and Len Type {isoFieldAttribute?.LenDataType}"); } switch (isoFieldAttribute.DataType) { case DataType.BIN: fieldBytes.AddRange(fieldValue.ToBinaryStringFromHex().ToBytesFromBinaryString()); break; case DataType.BCD: var bcdValue = fieldValue.ConvertToBinaryCodedDecimal(false); fieldBytes.AddRange(bcdValue); break; case DataType.ASCII: case DataType.HEX: fieldBytes.AddRange(fieldValue.FromASCIIToBytes(isoFieldAttribute.Encoding)); break; default: throw new BuildFieldException(isoFieldAttribute, $"Cannot Parse value for {isoFieldAttribute?.Position} and Type {isoFieldAttribute?.DataType}"); } } catch (Exception ex) { throw new BuildFieldException(isoFieldAttribute, $"Cannot Parse value for {isoFieldAttribute?.Position} and Type {isoFieldAttribute?.DataType}", ex); } return(fieldBytes.ToArray()); }
/// <summary> /// Parses bytes value to an object value /// </summary> /// <param name="isoFieldAttribute">iso Field Attribute</param> /// <param name="isoMessageBytes">whole Message bytes</param> /// <param name="currentPos">current Position of Parsed Message bytes, passed as a Reference</param> /// <returns>field object value</returns> internal static string GetFieldValue(this IsoFieldAttribute isoFieldAttribute, byte[] isoMessageBytes, ref int currentPos) { var fieldLen = 0; var fieldValue = string.Empty; var lengthBytes = (int)isoFieldAttribute.LengthType; try { switch (isoFieldAttribute.LengthType) { case LengthType.FIXED: case LengthType.LVAR: fieldLen = isoFieldAttribute.MaxLen; break; case LengthType.LLVAR: case LengthType.LLLVAR: if (isoFieldAttribute.LenDataType == DataType.ASCII) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldAttribute.Encoding); fieldLen = int.Parse(lenValue); } else if (isoFieldAttribute.LenDataType == DataType.HEX) { var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToASCIIString(isoFieldAttribute.Encoding); fieldLen = lenValue.HexValueToInt(); } else if (isoFieldAttribute.LenDataType == DataType.BCD) { lengthBytes = lengthBytes - 1; //BCD Always one byte less for Lentgh var lenValue = isoMessageBytes.Skip(currentPos).Take(lengthBytes).ToArray().BDCToString(); fieldLen = int.Parse(lenValue); } break; default: throw new ParseFieldException(isoFieldAttribute, $"Cannot Parse Length value for {isoFieldAttribute?.Position} and Len Type {isoFieldAttribute?.LenDataType}"); } currentPos = currentPos + lengthBytes; switch (isoFieldAttribute.DataType) { case DataType.BIN: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToStringFromBinary(); currentPos = currentPos + fieldLen; break; case DataType.BCD: if (isoFieldAttribute.ContentType != ContentType.B) { fieldLen = fieldLen % 2 == 1 ? (fieldLen / 2 + 1) : fieldLen / 2; } fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToArray().BDCToString(); currentPos = currentPos + fieldLen; break; case DataType.ASCII: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen).ToASCIIString(isoFieldAttribute.Encoding); currentPos = currentPos + fieldLen; break; case DataType.HEX: fieldValue = isoMessageBytes.Skip(currentPos).Take(fieldLen * 2).HexBytesToString(); currentPos = currentPos + (fieldLen * 2); break; default: throw new ParseFieldException(isoFieldAttribute, $"Cannot Parse value for {isoFieldAttribute?.Position} and Type {isoFieldAttribute?.DataType}"); } } catch (Exception ex) { throw new ParseFieldException(isoFieldAttribute, $"Cannot Parse value for {isoFieldAttribute?.Position} and Type {isoFieldAttribute?.DataType}", ex); } return(fieldValue); }
/// <summary> /// Contructor of Exception /// </summary> /// <param name="isoFieldAttr">iso field Attribute</param> /// <param name="innerEx">Inner exception details</param> /// <param name="exMessage">error message</param> public BuildFieldException(IsoFieldAttribute isoFieldAttr, string exMessage, Exception innerEx) : base(exMessage, innerEx) { IsoFieldData = isoFieldAttr; }
/// <summary> /// Contructor of Exception /// </summary> /// <param name="isoFieldAttr">iso field Attribute</param> /// <param name="exMessage">error message</param> public ParseFieldException(IsoFieldAttribute isoFieldAttr, string exMessage) : base(exMessage) { IsoFieldData = isoFieldAttr; }