diff --git a/src/CsvHelper.Performance/Program.cs b/src/CsvHelper.Performance/Program.cs
index 21b5bc85f..809f0522b 100644
--- a/src/CsvHelper.Performance/Program.cs
+++ b/src/CsvHelper.Performance/Program.cs
@@ -17,10 +17,8 @@ static void Main( string[] args )
//ReadGetField();
//ReadGetRecords();
- //WriteField( 50, 1000000);
- //WriteRecords( 1000000 );
-
- Console.ReadKey();
+ WriteField( 50, 1000000);
+ WriteRecords( 1000000 );
}
static string GetFilePath()
diff --git a/src/CsvHelper/CsvHelper.csproj b/src/CsvHelper/CsvHelper.csproj
index eaa63338e..fecebd63a 100644
--- a/src/CsvHelper/CsvHelper.csproj
+++ b/src/CsvHelper/CsvHelper.csproj
@@ -12,6 +12,7 @@
3.0.0.0
3.0.0.0
netstandard2.0
+ 7.1
true
CsvHelper
diff --git a/src/CsvHelper/CsvWriter.cs b/src/CsvHelper/CsvWriter.cs
index 36f8b689d..d84c26b80 100644
--- a/src/CsvHelper/CsvWriter.cs
+++ b/src/CsvHelper/CsvWriter.cs
@@ -395,19 +395,18 @@ public virtual void WriteDynamicHeader( IDynamicMetaObjectProvider record )
/// The record to write.
public virtual void WriteRecord( T record )
{
- var dynamicRecord = record as IDynamicMetaObjectProvider;
- if( dynamicRecord != null )
+ if( record is IDynamicMetaObjectProvider dynamicRecord )
{
if( context.WriterConfiguration.HasHeaderRecord && !context.HasHeaderBeenWritten )
{
WriteDynamicHeader( dynamicRecord );
- NextRecord();
+ NextRecord();
}
}
try
{
- GetWriteRecordAction( record ).DynamicInvoke( record );
+ GetWriteRecordAction( record ).Invoke( record );
context.HasHeaderBeenWritten = true;
}
catch( Exception ex )
@@ -446,13 +445,12 @@ public virtual void WriteRecords( IEnumerable records )
{
recordType = record.GetType();
- var dynamicObject = record as IDynamicMetaObjectProvider;
- if( dynamicObject != null )
+ if( record is IDynamicMetaObjectProvider dynamicObject )
{
if( context.WriterConfiguration.HasHeaderRecord && !context.HasHeaderBeenWritten )
{
WriteDynamicHeader( dynamicObject );
- NextRecord();
+ NextRecord();
}
}
else
@@ -463,13 +461,13 @@ public virtual void WriteRecords( IEnumerable records )
if( context.WriterConfiguration.HasHeaderRecord && !context.HasHeaderBeenWritten && !isPrimitive )
{
WriteHeader( recordType );
- NextRecord();
+ NextRecord();
}
}
- try
+ try
{
- GetWriteRecordAction( record ).DynamicInvoke( record );
+ GetWriteRecordAction( record ).Invoke( record );
}
catch( TargetInvocationException ex )
{
@@ -605,7 +603,7 @@ protected virtual void Dispose( bool disposing )
/// The type of the custom class being written.
///
/// The action delegate.
- protected virtual Delegate GetWriteRecordAction( T record )
+ protected virtual Action GetWriteRecordAction( T record )
{
var type = typeof( T );
if( type == typeof( object ) )
@@ -613,13 +611,12 @@ protected virtual Delegate GetWriteRecordAction( T record )
type = record.GetType();
}
- Delegate action;
- if( !context.TypeActions.TryGetValue( type, out action ) )
+ if( !context.TypeActions.TryGetValue( type, out var action ) )
{
action = CreateWriteRecordAction( type, record );
}
- return action;
+ return (Action)action;
}
///
@@ -628,18 +625,17 @@ protected virtual Delegate GetWriteRecordAction( T record )
///
/// The type of the custom class being written.
/// The record that will be written.
- protected virtual Delegate CreateWriteRecordAction( Type type, T record )
+ /// The type of the record being written.
+ protected virtual Action CreateWriteRecordAction( Type type, T record )
{
- var expandoObject = record as ExpandoObject;
- if( expandoObject != null )
+ if( record is ExpandoObject expandoObject )
{
- return CreateActionForExpandoObject( expandoObject );
+ return CreateActionForExpandoObject( expandoObject );
}
-
- var dynamicObject = record as IDynamicMetaObjectProvider;
- if( dynamicObject != null )
+
+ if( record is IDynamicMetaObjectProvider dynamicObject )
{
- return CreateActionForDynamic( dynamicObject );
+ return CreateActionForDynamic( dynamicObject );
}
if( context.WriterConfiguration.Maps[type] == null )
@@ -650,19 +646,20 @@ protected virtual Delegate CreateWriteRecordAction( Type type, T record )
if( type.GetTypeInfo().IsPrimitive )
{
- return CreateActionForPrimitive( type );
+ return CreateActionForPrimitive( type );
}
- return CreateActionForObject( type );
+ return CreateActionForObject( type );
}
///
/// Creates the action for an object.
///
/// The type of object to create the action for.
- protected virtual Delegate CreateActionForObject( Type type )
+ protected virtual Action CreateActionForObject( Type type )
{
- var recordParameter = Expression.Parameter( type, "record" );
+ var recordParameter = Expression.Parameter( typeof( T ), "record" );
+ var recordParameterConverted = Expression.Convert( recordParameter, type );
// Get a list of all the members so they will
// be sorted properly.
@@ -674,16 +671,16 @@ protected virtual Delegate CreateActionForObject( Type type )
throw new WriterException( context, $"No properties are mapped for type '{type.FullName}'." );
}
- var delegates = new List();
+ var delegates = new List>();
foreach( var memberMap in members )
{
if( memberMap.Data.WritingConvertExpression != null )
{
// The user is providing the expression to do the conversion.
- Expression exp = Expression.Invoke( memberMap.Data.WritingConvertExpression, recordParameter );
+ Expression exp = Expression.Invoke( memberMap.Data.WritingConvertExpression, recordParameterConverted );
exp = Expression.Call( Expression.Constant( this ), nameof( WriteConvertedField ), null, exp );
- delegates.Add( Expression.Lambda( typeof( Action<> ).MakeGenericType( type ), exp, recordParameter ).Compile() );
+ delegates.Add( Expression.Lambda>( exp, recordParameter ).Compile() );
continue;
}
@@ -717,7 +714,7 @@ protected virtual Delegate CreateActionForObject( Type type )
continue;
}
- fieldExpression = CreateMemberExpression( recordParameter, context.WriterConfiguration.Maps[type], memberMap );
+ fieldExpression = CreateMemberExpression( recordParameterConverted, context.WriterConfiguration.Maps[type], memberMap );
var typeConverterExpression = Expression.Constant( memberMap.Data.TypeConverter );
memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge( new TypeConverterOptions(), context.WriterConfiguration.TypeConverterOptionsFactory.GetOptions( memberMap.Data.Member.MemberType() ), memberMap.Data.TypeConverterOptions );
@@ -729,15 +726,14 @@ protected virtual Delegate CreateActionForObject( Type type )
if( type.GetTypeInfo().IsClass )
{
- var areEqualExpression = Expression.Equal( recordParameter, Expression.Constant( null ) );
+ var areEqualExpression = Expression.Equal( recordParameterConverted, Expression.Constant( null ) );
fieldExpression = Expression.Condition( areEqualExpression, Expression.Constant( string.Empty ), fieldExpression );
}
}
var writeFieldMethodCall = Expression.Call( Expression.Constant( this ), nameof( WriteConvertedField ), null, fieldExpression );
- var actionType = typeof( Action<> ).MakeGenericType( type );
- delegates.Add( Expression.Lambda( actionType, writeFieldMethodCall, recordParameter ).Compile() );
+ delegates.Add( Expression.Lambda>( writeFieldMethodCall, recordParameter ).Compile() );
}
var action = CombineDelegates( delegates );
@@ -750,9 +746,9 @@ protected virtual Delegate CreateActionForObject( Type type )
/// Creates the action for a primitive.
///
/// The type of primitive to create the action for.
- protected virtual Delegate CreateActionForPrimitive( Type type )
+ protected virtual Action CreateActionForPrimitive( Type type )
{
- var recordParameter = Expression.Parameter( type, "record" );
+ var recordParameter = Expression.Parameter( typeof( T ), "record" );
Expression fieldExpression = Expression.Convert( recordParameter, typeof( object ) );
@@ -771,8 +767,7 @@ protected virtual Delegate CreateActionForPrimitive( Type type )
fieldExpression = Expression.Call( typeConverterExpression, method, fieldExpression, Expression.Constant( this ), Expression.Constant( memberMapData ) );
fieldExpression = Expression.Call( Expression.Constant( this ), nameof( WriteConvertedField ), null, fieldExpression );
- var actionType = typeof( Action<> ).MakeGenericType( type );
- var action = Expression.Lambda( actionType, fieldExpression, recordParameter ).Compile();
+ var action = Expression.Lambda>( fieldExpression, recordParameter ).Compile();
context.TypeActions[type] = action;
return action;
@@ -785,9 +780,9 @@ protected virtual Delegate CreateActionForPrimitive( Type type )
///
/// The ExpandoObject.
///
- protected virtual Delegate CreateActionForExpandoObject( ExpandoObject obj )
+ protected virtual Action CreateActionForExpandoObject( ExpandoObject obj )
{
- Action