/// <summary>
        /// Initializes a new instance of the <see cref="FileHierarchyReflector"/> class.
        /// </summary>
        /// <param name="index">The <see cref="Index"/>.</param>
        /// <param name="fh">The <see cref="FileHierarchy"/>.</param>
        /// <param name="pi">The <see cref="PropertyInfo"/>.</param>
        /// <param name="ff">The <see cref="FileFormat"/>.</param>
        internal FileHierarchyReflector(int index, FileHierarchyAttribute fh, PropertyInfo pi, FileFormatBase ff)
        {
            Index         = index;
            Order         = fh.Order < 0 ? int.MaxValue : fh.Order;
            FileHierarchy = fh;
            PropertyInfo  = pi;
            FileFormat    = ff;

            // Where an intrinsic type then we have an issue.
            if (FileColumnReflector.GetTypeCode(PropertyInfo.PropertyType) != TypeCode.Object)
            {
                throw new ArgumentException($"Type '{PropertyInfo.DeclaringType.Name}' Property '{PropertyInfo.Name}' must be a class or collection (FileHierarchyAttribute).", nameof(pi));
            }

            // Determine the collection type.
            _collTypeReflector = ComplexTypeReflector.Create(PropertyInfo);

            // Load/cache the corresponding property type.
            var frr = (_collTypeReflector.ComplexTypeCode == ComplexTypeCode.Object) ? FileFormat.GetFileRecordReflector(PropertyInfo.PropertyType) : FileFormat.GetFileRecordReflector(_collTypeReflector.ItemType);

            if (fh.ValidationType != null)
            {
                frr.SetValidatorType(fh.ValidationType);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="FileColumnReflector"/> class.
        /// </summary>
        /// <param name="index">The <see cref="Index"/>.</param>
        /// <param name="fc">The <see cref="FileColumn"/>.</param>
        /// <param name="pi">The <see cref="PropertyInfo"/>.</param>
        /// <param name="ff">The <see cref="FileFormat"/>.</param>
        internal FileColumnReflector(int index, FileColumnAttribute fc, PropertyInfo pi, FileFormatBase ff)
        {
            Index        = index;
            Order        = fc.Order < 0 ? int.MaxValue : fc.Order;
            Name         = string.IsNullOrEmpty(fc.Name) ? pi.Name : fc.Name;
            FileColumn   = fc;
            PropertyInfo = pi;
            FileFormat   = ff;

            // Get the property type being mindful of nullables.
            if (PropertyInfo.PropertyType.GetTypeInfo().IsGenericType&& PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                PropertyTypeCode   = GetTypeCode(PropertyInfo.PropertyType.GetGenericArguments()[0]);
                PropertyIsNullable = true;
            }
            else
            {
                PropertyTypeCode = GetTypeCode(PropertyInfo.PropertyType);
            }

            _valueConverter = FileFormat.Converters.Get(PropertyInfo.PropertyType, FileColumn.TextValueConverterKey, FileColumn.TextValueConverterType);
            if (!string.IsNullOrEmpty(FileColumn.TextValueConverterKey) && _valueConverter == null)
            {
                throw new InvalidOperationException(string.Format("FileColumnAttribute has TextValueConverterKey of '{0}' is not found within the FileFormat.Converters.", FileColumn.TextValueConverterKey));
            }

            if (FileColumn.IsLineNumber && PropertyTypeCode != TypeCode.Int32 && PropertyTypeCode != TypeCode.Int64)
            {
                throw new InvalidOperationException("FileColumnAttribute has IsLineNumber set to true; the underlying property type must be either Int32 or Int64.");
            }
        }
Exemple #3
0
        /// <summary>
        /// Gets the underlying hierarchy for the specified <see cref="FileFormatBase"/>.
        /// </summary>
        /// <param name="fileFormat">The <see cref="FileFormatBase"/>.</param>
        /// <returns>A dictionary containing the full hierarchy.</returns>
        public static Dictionary <string, FileRecordHierarchyItem> GetHierarchy(FileFormatBase fileFormat)
        {
            var dict = new Dictionary <string, FileRecordHierarchyItem>();

            Get(fileFormat, dict, new FileRecordHierarchyItem {
                RecordIdentifier = fileFormat.ContentRecordIdentifier, Level = 0, Parent = null, RecordReflector = fileFormat.GetFileRecordReflector(fileFormat.ContentRowType)
            }, null);
            return(dict);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="FileColumnReflector"/> class.
        /// </summary>
        internal FileRecordReflector(Type type, FileFormatBase ff)
        {
            Type     = type;
            TypeInfo = type.GetTypeInfo();
            if (!TypeInfo.IsClass)
            {
                throw new ArgumentException($"Type '{type.Name}' must be a class.", nameof(type));
            }

            // Get all the property/column metadata.
            FileFormat = ff;
            int i        = 0;
            var columns  = new List <FileColumnReflector>();
            var children = new List <FileHierarchyReflector>();

            foreach (var pi in TypeReflector.GetProperties(Type))
            {
                i++;
                var fca = pi.GetCustomAttribute <FileColumnAttribute>();
                var fha = pi.GetCustomAttribute <FileHierarchyAttribute>();

                if (fca != null && fha != null)
                {
                    throw new InvalidOperationException($"Type '{type.Name}' property '{pi.Name}' cannot specify both a FileColumnAttribute and FileHierarchyAttribute.");
                }

                if (fca != null)
                {
                    columns.Add(new FileColumnReflector(i, fca, pi, FileFormat));
                }

                if (fha != null)
                {
                    var fhr = new FileHierarchyReflector(i, fha, pi, ff);
                    if (children.SingleOrDefault(x => x.RecordIdentifier == fhr.RecordIdentifier) != null)
                    {
                        throw new InvalidOperationException($"Type '{type.Name}' property '{pi.Name}' FileHierarchyAttribute has a duplicate Record Identifier '{fhr.RecordIdentifier}' (must be unique within Type).");
                    }

                    children.Add(new FileHierarchyReflector(i, fha, pi, ff));
                }
            }

            // Order the Columns and Children by Order and Index for usage.
            Columns  = columns.OrderBy(x => x.Order).ThenBy(x => x.Index).ToList();
            Children = children.OrderBy(x => x.Order).ThenBy(x => x.Index).ToList();

            for (int j = 0; j < Children.Count; j++)
            {
                _childrenIndexes.Add(Children[j].RecordIdentifier, j);
            }
        }
        /// <summary>
        /// Gets the underlying hierarchy for an item.
        /// </summary>
        private static void Get(FileFormatBase fileFormat, Dictionary <string, FileRecordHierarchyItem> dict, FileRecordHierarchyItem item, PropertyInfo pi)
        {
            if (dict.ContainsKey(item.RecordIdentifier))
            {
                throw new InvalidOperationException(string.Format("Type '{0}' property '{1}' FileHierarchyAttribute has a duplicate Record Identifier '{2}'; must be unique within hierarchy).",
                                                                  pi.DeclaringType.Name, pi.Name, item.RecordIdentifier));
            }

            if (fileFormat.HeaderRecordIdentifier != null && item.RecordIdentifier == fileFormat.HeaderRecordIdentifier)
            {
                throw new InvalidOperationException(string.Format("Type '{0}' property '{1}' FileHierarchyAttribute has a duplicate Record Identifier '{2}'; must be different to the Header Record Identifier).",
                                                                  pi.DeclaringType.Name, pi.Name, item.RecordIdentifier));
            }

            if (fileFormat.TrailerRecordIdentifier != null && item.RecordIdentifier == fileFormat.TrailerRecordIdentifier)
            {
                throw new InvalidOperationException(string.Format("Type '{0}' property '{1}' FileHierarchyAttribute has a duplicate Record Identifier '{2}'; must be different to the Trailer Record Identifier).",
                                                                  pi.DeclaringType.Name, pi.Name, item.RecordIdentifier));
            }

            dict.Add(item.RecordIdentifier, item);

            if (item.RecordReflector.Children == null || item.RecordReflector.Children.Length == 0)
            {
                return;
            }

            foreach (var fhr in item.RecordReflector.Children)
            {
                var frhh = new FileRecordHierarchyItem
                {
                    RecordIdentifier   = fhr.RecordIdentifier,
                    Level              = item.Level + 1,
                    Parent             = item,
                    RecordReflector    = fileFormat.GetFileRecordReflector(fhr.PropertyType),
                    HierarchyReflector = fhr
                };

                Get(fileFormat, dict, frhh, fhr.PropertyInfo);
                item.Children.Add(frhh.RecordIdentifier, frhh);
            }
        }