< Summary

Class:WinSolutions.Sveta.Server.Data.DataLoading.Parsers.BaseParser`1
Assembly:WinSolutions.Sveta.Server
File(s):/opt/dev/sveta_api_build/WinSolutions.Sveta.Server/Data/DataLoading/Parsers/BaseParser.cs
Covered lines:0
Uncovered lines:38
Coverable lines:38
Total lines:126
Line coverage:0% (0 of 38)
Covered branches:0
Total branches:12
Branch coverage:0% (0 of 12)

Metrics

MethodLine coverage Branch coverage
.ctor()0%100%
IsNumericType(...)0%0%
LoadRecord(...)0%0%
Convert(...)0%0%

File(s)

/opt/dev/sveta_api_build/WinSolutions.Sveta.Server/Data/DataLoading/Parsers/BaseParser.cs

#LineLine coverage
 1using System;
 2using System.Data;
 3using System.Collections.Generic;
 4using System.Globalization;
 5using System.IO;
 6using System.Linq;
 7using System.Reflection;
 8using System.Text;
 9using WinSolutions.Sveta.Server.Data.DataLoading.Records;
 10using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 11
 12namespace WinSolutions.Sveta.Server.Data.DataLoading.Parsers
 13{
 14    public abstract class BaseParser<T> : IParser where T : BaseRecord, new()
 15    {
 016        protected List<FieldMap> Map = new List<FieldMap>();
 17
 018        public BaseParser()
 019        {
 020            Map.AddRange((new T() as IExternalRecord).GetMapping());
 021        }
 22
 23        public IEnumerable<BaseRecord> Parse(Stream stream)
 24        {
 25            var dt = ReadLines(stream);
 26
 27            foreach (var mapField in Map)
 28            {
 29                var column = dt.Columns[mapField.PropertyInfo.Name];
 30                if (column == null)
 31                {
 32                    throw new ArgumentException($"Поле {mapField.PropertyInfo.Name} не найдено");
 33                }
 34            }
 35
 36            int lineNumber = 0;
 37
 38            foreach (DataRow row in dt.Select())
 39            {
 40                lineNumber++;
 41
 42                var rec = new T();
 43                try
 44                {
 45                    LoadRecord(rec, row);
 46
 47                    if (rec is IExternalRecord er)
 48                    {
 49                        er.Line = new List<string>();
 050                        er.Line.AddRange(row.ItemArray.Select(x => x == null ? "" : x.ToString()));
 51                        er.LineNumber = lineNumber;
 52                    }
 53                }
 54                catch (Exception ex)
 55                {
 56                    if (rec is IExternalRecord erx)
 57                    {
 58                        erx.Exception = ex;
 59                    }
 60                }
 61
 62                yield return rec;
 63            }
 64        }
 65
 66        protected bool IsNumericType(Type type)
 067        {
 068            switch (Type.GetTypeCode(type))
 69            {
 70                case TypeCode.Byte:
 71                case TypeCode.SByte:
 72                case TypeCode.UInt16:
 73                case TypeCode.UInt32:
 74                case TypeCode.UInt64:
 75                case TypeCode.Int16:
 76                case TypeCode.Int32:
 77                case TypeCode.Int64:
 78                case TypeCode.Decimal:
 79                case TypeCode.Double:
 80                case TypeCode.Single:
 081                    return true;
 82                default:
 083                    return false;
 84            }
 085        }
 86
 87        protected void LoadRecord(BaseRecord rec, DataRow vals)
 088        {
 089            for(int i = 0; i < vals.Table.Columns.Count; i++)
 090            {
 091                var mapField = Map.Single(x => x.PropertyInfo.Name.ToLower() == vals.Table.Columns[i].ColumnName.ToLower
 092                var v = Convert(vals[i].ToString(), mapField.PropertyInfo);
 093                mapField.PropertyInfo.SetValue(rec, v);
 094            }
 095        }
 96
 097        readonly NumberFormatInfo numberFormat = new NumberFormatInfo
 098        {
 099            NumberDecimalSeparator = ".",
 0100            NumberGroupSeparator = ""
 0101        };
 102
 103        object Convert(string val, PropertyInfo pi)
 0104        {
 0105            if (IsNumericType(pi.PropertyType))
 0106            {
 0107                val = val.Replace(",", ".");
 0108            }
 109
 110            try
 0111            {
 0112                return System.Convert.ChangeType(val, pi.PropertyType, numberFormat);
 113            }
 0114            catch (FormatException)
 0115            {
 0116                if (IsNumericType(pi.PropertyType))
 0117                {
 0118                    return System.Convert.ChangeType(1, pi.PropertyType, numberFormat);
 119                }
 0120                throw new FormatException($"Ошибка разбора значения \"{val}\" для поля \"{pi.Name}\"");
 121            }
 0122        }
 123
 124        protected abstract DataTable ReadLines(Stream stream);
 125    }
 126}