예제 #1
0
        /// <summary>
        /// Constructs a serialization helper object separate from I/O
        /// </summary>
        /// <param name="settings"></param>
        /// <param name="riskyChars"></param>
        /// <param name="forceQualifierTypes"></param>
        public SerializationHelper(CSVSettings settings, char[] riskyChars, Dictionary <Type, int> forceQualifierTypes)
        {
            _settings = settings;
            if (_settings == null)
            {
                _settings = CSVSettings.CSV;
            }

            // Extract properties and fields that are not excluded
            var excluded = new ExcludedColumnHelper(_settings);
            var props    = new List <PropertyInfo>();

            foreach (var prop in typeof(T).GetProperties())
            {
                if (!excluded.IsExcluded(prop.Name))
                {
                    props.Add(prop);
                }
            }

            var fields = new List <FieldInfo>();

            foreach (var field in typeof(T).GetFields())
            {
                if (!excluded.IsExcluded(field.Name))
                {
                    fields.Add(field);
                }
            }

            _properties          = props.ToArray();
            _fields              = fields.ToArray();
            _riskyChars          = riskyChars;
            _forceQualifierTypes = forceQualifierTypes;
        }
예제 #2
0
        /// <summary>
        /// Construct a new deserialization helper for a specific class containing all the information necessary
        /// for optimized deserialization
        /// </summary>
        /// <param name="settings"></param>
        /// <param name="headers"></param>
        public DeserializationHelper(CSVSettings settings, string[] headers)
        {
            var settings1 = settings;

            if (settings1 == null)
            {
                settings1 = CSVSettings.TSV;
            }
            if (headers == null)
            {
                throw new Exception("CSV must have headers to be deserialized");
            }
            var return_type = typeof(T);

            _numColumns = headers.Length;

            // Set binding flags correctly
            var bindings = BindingFlags.Public | BindingFlags.Instance;

            if (!settings1.HeadersCaseSensitive)
            {
                bindings |= BindingFlags.IgnoreCase;
            }

            // Set up the list of excluded columns
            var excluded = new ExcludedColumnHelper(settings1);

            // Determine how to handle each column in the file - check properties, fields, and methods
            _columnTypes = new Type[_numColumns];
            _converters  = new TypeConverter[_numColumns];
            _properties  = new PropertyInfo[_numColumns];
            _fields      = new FieldInfo[_numColumns];
            _methods     = new MethodInfo[_numColumns];
            for (var i = 0; i < _numColumns; i++)
            {
                // Is this column excluded?
                if (excluded.IsExcluded(headers[i]))
                {
                    continue;
                }

                // Check if this is a property
                _properties[i] = return_type.GetProperty(headers[i], bindings);
                if (_properties[i] != null && !_properties[i].CanWrite)
                {
                    if (settings1.IgnoreReadOnlyProperties && settings1.IgnoreHeaderErrors)
                    {
                        _properties[i] = null;
                        continue;
                    }
                    throw new Exception($"The column header '{headers[i]}' matches a read-only property. To ignore this exception, enable IgnoreReadOnlyProperties and IgnoreHeaderErrors.");
                }

                // If we failed to get a property handler, let's try a field handler
                if (_properties[i] == null)
                {
                    _fields[i] = return_type.GetField(headers[i], bindings);

                    // If we failed to get a field handler, let's try a method
                    if (_fields[i] == null)
                    {
                        // Methods must be treated differently - we have to ensure that the method has a single parameter
                        var mi = return_type.GetMethod(headers[i], bindings);
                        if (mi != null)
                        {
                            if (mi.GetParameters().Length == 1)
                            {
                                _methods[i]     = mi;
                                _columnTypes[i] = mi.GetParameters()[0].ParameterType;
                            }
                            else if (!settings1.IgnoreHeaderErrors)
                            {
                                throw new Exception(
                                          $"The column header '{headers[i]}' matched a method with more than one parameter.");
                            }
                        }
                        else if (!settings1.IgnoreHeaderErrors)
                        {
                            throw new Exception(
                                      $"The column header '{headers[i]}' was not found in the class '{return_type.FullName}'.");
                        }
                    }
                    else
                    {
                        _columnTypes[i] = _fields[i].FieldType;
                    }
                }
                else
                {
                    _columnTypes[i] = _properties[i].PropertyType;
                }

                if (_columnTypes[i] != null)
                {
                    _converters[i] = TypeDescriptor.GetConverter(_columnTypes[i]);
                    if (_converters[i] == null && !settings1.IgnoreHeaderErrors)
                    {
                        throw new Exception(
                                  $"The column {headers[i]} (type {_columnTypes[i]}) does not have a type converter.");
                    }
                }
            }
        }