/// <summary> /// Writes a single element record to the stream. This method does NOT write out the header row! /// </summary> /// <typeparam name="T">Type of business object</typeparam> /// <param name="instances">Instance of business object to write</param> /// <param name="writeHeader">We will write out the header ONLY if this is TRUE. Default: FALSE</param> public void WriteRecords <T>(IEnumerable <T> instances, bool writeHeader = false) where T : class, new() { ClassInfo objectInfo = TypeInspector.InspectOnlyMembersAnotated <T, FileFieldAttribute>(); string[] headers = GetHeader <T>(objectInfo); if (writeHeader) { for (int h = 0; h < headers.Length; h++) { string element = headers[h]; if (element != null) { writer.Write("\""); writer.Write(element); writer.Write("\""); } if (h < (headers.Length - 1)) { writer.Write(DELIMITER); } } writer.WriteLine(); } foreach (T instance in instances) { WriteElements(GetRecord(instance, headers, objectInfo)); } writer.Flush(); }
/// <summary> /// Writes a single element record to the stream. This method does NOT write out the header row! /// </summary> /// <typeparam name="T">Type of business object</typeparam> /// <param name="instance">Instance of business object to write</param> public void WriteRecord <T>(T instance) where T : class, new() { ClassInfo objectInfo = TypeInspector.InspectOnlyMembersAnotated <T, FileFieldAttribute>(); string[] headers = GetHeader <T>(objectInfo); WriteElements(GetRecord(instance, headers, objectInfo)); }
/// <summary> /// Gets the record data as a string array /// </summary> /// <typeparam name="T">Type of business object</typeparam> /// <param name="instance">Instance of business object to turn into a record-array</param> /// <param name="headers">Headers for the object (NULL to auto-detect -- bad idea when fetching for multiple items)</param> /// <param name="objectInfo">Reflected object metadata (NULL to auto-detect -- bad idea when fetching for multiple items)</param> /// <returns>String array containing records</returns> public string[] GetRecord <T>(T instance, string[] headers = null, ClassInfo objectInfo = null) where T : class, new() { objectInfo ??= TypeInspector.InspectOnlyMembersAnotated <T, FileFieldAttribute>(); headers ??= GetHeader <T>(objectInfo); string[] record = new string[objectInfo.Properties.Count + objectInfo.Fields.Count]; foreach (PropertyInfo property in objectInfo.Properties) { object objValue = property.Read(instance); FileFieldAttribute ffAttribute = property.GetAttributes <FileFieldAttribute>().First(); if (objValue == null) { objValue = ffAttribute.NullValue; } else { if (property.Type.IsEnum && (ffAttribute.UseEnumIntegerValue)) { // by default, reflection would have given us the name (in objValue) objValue = (int)objValue; } else if (property.Type == typeof(bool)) { objValue = ((bool)objValue ? (ffAttribute.BooleanTrues?[0] ?? "true") : (ffAttribute.BooleanFalses?[0] ?? "false")); } else if (property.Type == typeof(bool?)) { bool?b = (bool?)objValue; if (b.HasValue) { objValue = (b.Value ? (ffAttribute.BooleanTrues?[0] ?? "true") : (ffAttribute.BooleanFalses?[0] ?? "false")); } } else if (property.IsEnumerable) { string serialized = JsonSerializer.Serialize( objValue, property.Type, new JsonSerializerOptions() { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping } ); if ((serialized.Length > 0) && (serialized[0] == '[')) { serialized = serialized[1..];
/// <summary> /// Create the FIELD_PROPERTY_MAP /// </summary> /// <typeparam name="ClassT">Type of the class object we need to deserialize into</typeparam> private PropertyFieldMappingInfo[] MapHeaderToClass <ClassT>() where ClassT : class, new() { ClassInfo info = TypeInspector.InspectOnlyMembersAnotated <ClassT, FileFieldAttribute>(); if (info == null) { throw new InvalidOperationException($"The type '{typeof(ClassT).Name}' contains no usable properties/fields. Ensure the properties/fields are decorated with the 'FileFieldAttribute' attribute."); } List <PropertyFieldMappingInfo> tempList = new List <PropertyFieldMappingInfo>(); int maxColumnIndex = -1; for (int i = 0; i < info.Fields.Count; i++) { PropertyFieldMappingInfo map = new PropertyFieldMappingInfo(info.Fields[i]); if ((map.ColumnIndex < 0) && (HEADER != null)) { foreach (DataColumn col in HEADER.Columns) { if (col.Value == map.Attribute.Name) { map.ColumnIndex = col.Index; break; } } } if (map.ColumnIndex >= 0) { if (map.ColumnIndex > maxColumnIndex) { maxColumnIndex = map.ColumnIndex; } tempList.Add(map); } } for (int i = 0; i < info.Properties.Count; i++) { PropertyFieldMappingInfo map = new PropertyFieldMappingInfo(info.Properties[i]); if ((map.ColumnIndex < 0) && (HEADER != null)) { foreach (DataColumn col in HEADER.Columns) { if (col.Value == map.Attribute.Name) { map.ColumnIndex = col.Index; break; } } } if (map.ColumnIndex >= 0) { if (map.ColumnIndex > maxColumnIndex) { maxColumnIndex = map.ColumnIndex; } tempList.Add(map); } } if (tempList.Count == 0) { throw new InvalidOperationException($"The type '{typeof(ClassT).Name}' contains no usable properties/fields. Ensure the properties/fields are decorated with the 'FileFieldAttribute' attribute."); } PropertyFieldMappingInfo[] FIELD_PROPERTY_MAP = new PropertyFieldMappingInfo[maxColumnIndex + 1]; foreach (PropertyFieldMappingInfo item in tempList) { FIELD_PROPERTY_MAP[item.ColumnIndex] = item; } return(FIELD_PROPERTY_MAP); }