LINQtoCSV icon indicating copy to clipboard operation
LINQtoCSV copied to clipboard

Parsing nullable decimal fails

Open chrispday opened this issue 9 years ago • 1 comments

Parsing a field declared as decimal? fails with a FormatException with the value "2,000,000".

This is caused because when the TypeFieldInfo class (inside FieldMapper<T> class) sets up the converters it uses the fields PropertyType or FieldType to determine if that type has a Parse or ParseExact method (FieldMapper.cs lines 96-114). If it doesn't it falls back to a type converter. Unfortunately the type converter hard codes NumberStyles.Float (DecimalConverter.FromString(string, NumberFormatInfo) which won't parse decimal strings with a comma as a thousands seperator.

To fix the field type should be checked for nullable, and if it is to use the underlying type to test for a Parse or ParseExact method.

The only work around as it currently stands is to change the type of the field from decimal? to decimal and use the CanBeNull=true attribute.

chrispday avatar Aug 18 '15 02:08 chrispday

@chrispday I haven't done an official pull request yet, but I ran into the same problem today. I put together a quick bit of code to fix it; you're welcome to use it as-is or improve it if needed. I have not done full testing on it, but it is covering my needs so far. Hope this can help!

In FieldMapper.cs, I went to the AnalyzeTypeField method and entered the following block, replacing the section of code between the //parseNumberMethod comment block and the //Process the attributes comment block.

        var type = tfi.fieldType;
        var isNullable = type.IsGenericType && type.GetGenericTypeDefinition( ) == typeof( Nullable<> );
        if ( isNullable )
            type = type.GetGenericArguments( )[0];

        tfi.parseNumberMethod =
            type.GetMethod( "Parse",
                new Type[] { typeof( String ), typeof( NumberStyles ), typeof( IFormatProvider ) } );

        if ( tfi.parseNumberMethod == null )
        {
            if ( m_fileDescription.UseOutputFormatForParsingCsvValue )
            {
                tfi.parseExactMethod = type.GetMethod( "ParseExact",
                    new Type[] { typeof( string ), typeof( string ), typeof( IFormatProvider ) } );
            }

            tfi.typeConverter = null;
            if ( tfi.parseExactMethod == null )
            {
                tfi.typeConverter =
                    TypeDescriptor.GetConverter( type );
            }
        }

aifdsc avatar Dec 16 '15 17:12 aifdsc