Exemplo n.º 1
0
 /// <summary>
 /// Read the attributes of the class and create an array
 /// of how to process the file
 /// </summary>
 /// <param name="recordType">Class we are analysing</param>
 /// <param name="typedRecordAttribute"></param>
 internal VisynRecordInfo(Type recordType, ITypedRecordAttribute typedRecordAttribute)
 {
     RecordType = recordType;
     SizeHint   = 32;
     RecordConditionSelector = string.Empty;
     RecordCondition         = RecordCondition.None;
     CommentAnyPlace         = true;
     Operations = new RecordOperations(this);
     InitRecordFields(typedRecordAttribute);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Parse the attributes on the class and create an ordered list of
        /// fields we are extracting from the record
        /// </summary>
        /// <param name="fields">Complete list of fields in class</param>
        /// <param name="recordAttribute">Type of record, fixed or delimited</param>
        /// <returns>List of fields we are extracting</returns>
        private static FieldBase[] CreateCoreFields(IList <FieldInfo> fields, ITypedRecordAttribute recordAttribute)
        {
            var resFields = new List <FieldBase>();

            // count of Properties
            var automaticFields = 0;

            // count of normal fields
            var genericFields = 0;

            for (int i = 0; i < fields.Count; i++)
            {
                FieldBase currentField = FieldBase.CreateField(fields[i], recordAttribute);
                if (currentField == null)
                {
                    continue;
                }

                if (currentField.FieldInfo.IsDefined(typeof(CompilerGeneratedAttribute), false))
                {
                    automaticFields++;
                }
                else
                {
                    genericFields++;
                }

                // Add to the result
                resFields.Add(currentField);

                if (resFields.Count > 1)
                {
                    CheckForOrderProblems(currentField, resFields);
                }
            }

            if (automaticFields > 0 &&
                genericFields > 0 && SumOrder(resFields) == 0)
            {
                throw new BadUsageException(Messages.Messages.Errors.MixOfStandardAndAutoPropertiesFields
                                            .ClassName(resFields[0].FieldInfo.DeclaringType.Name)
                                            .Text);
            }

            SortFieldsByOrder(resFields);

            CheckForOptionalAndArrayProblems(resFields);

            return(resFields.ToArray());
        }
Exemplo n.º 3
0
        /// <summary>
        /// Create a list of fields we are extracting and set
        /// the size hint for record I/O
        /// </summary>
        private void InitRecordFields(ITypedRecordAttribute typedRecordAttribute)
        {
            ITypedRecordAttribute recordAttribute = Attributes.GetFirstInherited <TypedRecordAttribute>(RecordType);

            if (recordAttribute == null)
            {
                if (typedRecordAttribute == null)
                {
                    throw new BadUsageException(Messages.Messages.Errors.ClassWithOutRecordAttribute.ClassName(RecordType.Name).Text);
                }
                recordAttribute = typedRecordAttribute;
            }

            if (ReflectionHelper.GetDefaultConstructor(RecordType) == null)
            {
                throw new BadUsageException(Messages.Messages.Errors.ClassWithOutDefaultConstructor
                                            .ClassName(RecordType.Name)
                                            .Text);
            }

            Attributes.WorkWithFirst <IgnoreFirstAttribute>(
                RecordType,
                a => IgnoreFirst = a.NumberOfLines);

            Attributes.WorkWithFirst <IgnoreLastAttribute>(
                RecordType,
                a => IgnoreLast = a.NumberOfLines);

            Attributes.WorkWithFirst <IgnoreEmptyLinesAttribute>(
                RecordType,
                a => {
                IgnoreEmptyLines  = true;
                IgnoreEmptySpaces = a.IgnoreSpaces;
            });

#pragma warning disable CS0618 // Type or member is obsolete
            Attributes.WorkWithFirst <IgnoreCommentedLinesAttribute>(
#pragma warning restore CS0618 // Type or member is obsolete
                RecordType,
                a => {
                IgnoreEmptyLines = true;
                CommentMarker    = a.CommentMarker;
                CommentAnyPlace  = a.AnyPlace;
            });

            Attributes.WorkWithFirst <ConditionalRecordAttribute>(RecordType,
                                                                  a => {
                RecordCondition         = a.Condition;
                RecordConditionSelector = a.ConditionSelector;

                if (RecordCondition == RecordCondition.ExcludeIfMatchRegex || RecordCondition == RecordCondition.IncludeIfMatchRegex)
                {
                    RecordConditionRegEx = new Regex(RecordConditionSelector, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
                }
            });

            if (CheckInterface(RecordType, typeof(INotifyRead)))
            {
                NotifyRead = true;
            }

            if (CheckInterface(RecordType, typeof(INotifyWrite)))
            {
                NotifyWrite = true;
            }

            // Create fields
            // Search for cached fields
            var fields = new List <FieldInfo>(ReflectionHelper.RecursiveGetFields(RecordType));

            Fields = CreateCoreFields(fields, recordAttribute);

            if (FieldCount == 0)
            {
                throw new BadUsageException(Messages.Messages.Errors.ClassWithOutFields.ClassName(RecordType.Name).Text);
            }

            if (recordAttribute is FixedLengthRecordAttribute)
            {   // Defines the initial size of the StringBuilder
                SizeHint = 0;
                for (var i = 0; i < FieldCount; i++)
                {
                    SizeHint += ((FixedLengthField)Fields[i]).FieldLength;
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Check the Attributes on the field and return a structure containing
        /// the settings for this file.
        /// </summary>
        /// <param name="fi">Information about this field</param>
        /// <param name="recordAttribute">Type of record we are reading</param>
        /// <returns>Null if not used</returns>
        public static FieldBase CreateField(FieldInfo fi, ITypedRecordAttribute recordAttribute)
        {
            FieldBase  res               = null;
            MemberInfo mi                = fi;
            var        memberName        = $"The field: '{ fi.Name}'";
            var        fieldType         = fi.FieldType;
            var        fieldFriendlyName = AutoPropertyName(fi);

            if (string.IsNullOrEmpty(fieldFriendlyName) == false)
            {
                var prop = fi.DeclaringType.GetProperty(fieldFriendlyName);
                if (prop != null)
                {
                    memberName = $"The property: '{ prop.Name}'";
                    mi         = prop;
                }
                else
                {
                    fieldFriendlyName = null;
                }
            }
            // If ignored, return null
#pragma warning disable 612,618 // disable obsolete warning
            if (mi.IsDefined(typeof(FieldNotInFileAttribute), true) ||
                mi.IsDefined(typeof(FieldIgnoredAttribute), true) ||
                mi.IsDefined(typeof(FieldHiddenAttribute), true))
#pragma warning restore 612,618
            {
                return(null);
            }

            var attributes = (FieldAttribute[])mi.GetCustomAttributes(typeof(FieldAttribute), true);

            // CHECK USAGE ERRORS !!!

            // Fixed length record and no attributes at all
            if (recordAttribute is FixedLengthRecordAttribute && attributes.Length == 0)
            {
                throw new BadUsageException($"{memberName} must be marked the FieldFixedLength attribute because the record class is marked with FixedLengthRecord.");
            }

            if (attributes.Length > 1)
            {
                throw new BadUsageException($"{memberName} has a FieldFixedLength and a FieldDelimiter attribute.");
            }

            if (recordAttribute is DelimitedRecordAttribute && mi.IsDefined(typeof(FieldAlignAttribute), false))
            {
                throw new BadUsageException($"{memberName} can't be marked with FieldAlign attribute, it is only valid for fixed length records and are used only for write purpose.");
            }

            if (fieldType.IsArray == false && mi.IsDefined(typeof(FieldArrayLengthAttribute), false))
            {
                throw new BadUsageException($"{memberName} can't be marked with FieldArrayLength attribute is only valid for array fields.");
            }

            // PROCESS IN NORMAL CONDITIONS
            if (attributes.Length > 0)
            {
                var fieldAttribute = attributes[0];

                var fixedLengthAttribute = fieldAttribute as FieldFixedLengthAttribute;
                if (fixedLengthAttribute != null)
                {
                    // Fixed Field
                    if (recordAttribute is DelimitedRecordAttribute)
                    {
                        throw new BadUsageException($"{memberName} can't be marked with FieldFixedLength attribute, it is only for the FixedLengthRecords not for delimited ones.");
                    }

                    var alignAttribute = mi.GetFirst <FieldAlignAttribute>();

                    res = new FixedLengthField(fi, fixedLengthAttribute.Length, alignAttribute);
                    ((FixedLengthField)res).FixedMode = ((FixedLengthRecordAttribute)recordAttribute).FixedMode;
                }
                else if (fieldAttribute is FieldDelimiterAttribute)
                {
                    // Delimited Field
                    if (recordAttribute is FixedLengthRecordAttribute)
                    {
                        throw new BadUsageException($"{memberName} can't be marked with FieldDelimiter attribute, it is only for DelimitedRecords not for fixed ones.");
                    }
                    res = new DelimitedField(fi, ((FieldDelimiterAttribute)fieldAttribute).Delimiter);
                }
                else
                {
                    throw new BadUsageException(
                              $"Custom field attributes are not currently supported. Unknown attribute: {fieldAttribute.GetType().Name} on field: { fi.Name}");
                }
            }
            else // attributes.Length == 0
            {
                var delimitedRecordAttribute = recordAttribute as DelimitedRecordAttribute;

                if (delimitedRecordAttribute != null)
                {
                    res = new DelimitedField(fi, delimitedRecordAttribute.Delimiter);
                }
            }

            if (res != null)
            {
                // FieldDiscarded
                res.Discarded = mi.IsDefined(typeof(FieldValueDiscardedAttribute), false);

                // FieldTrim
                mi.WorkWithFirst <FieldTrimAttribute>((x) => {
                    res.TrimMode  = x.TrimMode;
                    res.TrimChars = x.TrimChars;
                });

                // FieldQuoted
                mi.WorkWithFirst <FieldQuotedAttribute>((x) => {
                    if (res is FixedLengthField)
                    {
                        throw new BadUsageException($"{memberName} can't be marked with FieldQuoted attribute, it is only for the delimited records.");
                    }

                    ((DelimitedField)res).QuoteChar      = x.QuoteChar;
                    ((DelimitedField)res).QuoteMode      = x.QuoteMode;
                    ((DelimitedField)res).QuoteMultiline = x.QuoteMultiline;
                });

                // FieldOrder
                mi.WorkWithFirst <FieldOrderAttribute>(x => res.FieldOrder = x.Order);

                // FieldCaption
                mi.WorkWithFirst <FieldCaptionAttribute>(x => res.FieldCaption = x.Caption);

                // FieldOptional
                res.IsOptional = mi.IsDefined(typeof(FieldOptionalAttribute), false);

                // FieldInNewLine
                res.InNewLine = mi.IsDefined(typeof(FieldInNewLineAttribute), false);

                // FieldNotEmpty
                res.IsNotEmpty = mi.IsDefined(typeof(FieldNotEmptyAttribute), false);

                // FieldArrayLength
                if (fieldType.IsArray)
                {
                    res.IsArray   = true;
                    res.ArrayType = fieldType.GetElementType();

                    // MinValue indicates that there is no FieldArrayLength in the array
                    res.ArrayMinLength = int.MinValue;
                    res.ArrayMaxLength = int.MaxValue;

                    mi.WorkWithFirst <FieldArrayLengthAttribute>((x) => {
                        res.ArrayMinLength = x.MinLength;
                        res.ArrayMaxLength = x.MaxLength;

                        if (res.ArrayMaxLength < res.ArrayMinLength || res.ArrayMinLength < 0 || res.ArrayMaxLength <= 0)
                        {
                            throw new BadUsageException($"{memberName} has invalid length values in the [FieldArrayLength] attribute.");
                        }
                    });
                }
            }

            if (string.IsNullOrEmpty(res.FieldFriendlyName))
            {
                res.FieldFriendlyName = res.FieldName;
            }

            return(res);
        }