2
2
using CsvHelper . Configuration ;
3
3
using System . Collections ;
4
4
using System . Globalization ;
5
- using System . Reflection ;
6
5
7
- namespace RestSharp . Serializers . CsvHelper {
8
- public class CsvHelperSerializer : IDeserializer , IRestSerializer , ISerializer {
9
- private const string TextCsvContentType = "text/csv" ;
6
+ namespace RestSharp . Serializers . CsvHelper ;
10
7
11
- private readonly CsvConfiguration _configuration ;
8
+ public class CsvHelperSerializer : IDeserializer , IRestSerializer , ISerializer {
9
+ const string TextCsvContentType = "text/csv" ;
12
10
13
- public ISerializer Serializer {
14
- get {
15
- return this ;
16
- }
17
- }
11
+ readonly CsvConfiguration _configuration ;
12
+
13
+ public ISerializer Serializer => this ;
14
+
15
+ public IDeserializer Deserializer => this ;
16
+
17
+ public string [ ] AcceptedContentTypes => new [ ] { TextCsvContentType , "application/x-download" } ;
18
+
19
+ public SupportsContentType SupportsContentType => x => Array . IndexOf ( AcceptedContentTypes , x ) != - 1 || x . Contains ( "csv" ) ;
20
+
21
+ public DataFormat DataFormat => DataFormat . None ;
22
+
23
+ public string ContentType { get ; set ; } = TextCsvContentType ;
24
+
25
+ public CsvHelperSerializer ( ) => _configuration = new CsvConfiguration ( CultureInfo . InvariantCulture ) ;
18
26
19
- public IDeserializer Deserializer {
20
- get {
21
- return this ;
27
+ public CsvHelperSerializer ( CsvConfiguration configuration ) => _configuration = configuration ;
28
+
29
+ public T ? Deserialize < T > ( RestResponse response ) {
30
+ try {
31
+ if ( response . Content == null )
32
+ throw new InvalidOperationException ( message : "Response content is null" ) ;
33
+
34
+ using var stringReader = new StringReader ( response . Content ) ;
35
+
36
+ using var csvReader = new CsvReader ( stringReader , CultureInfo . CurrentCulture ) ;
37
+
38
+ var @interface = typeof ( T ) . GetInterface ( "IEnumerable`1" ) ;
39
+
40
+ if ( @interface == null ) {
41
+ csvReader . Read ( ) ;
42
+
43
+ return csvReader . GetRecord < T > ( ) ;
22
44
}
23
- }
24
45
25
- public string [ ] AcceptedContentTypes {
26
- get {
27
- return new string [ ] { TextCsvContentType , "application/x-download" } ;
46
+ var itemType = @interface . GenericTypeArguments [ 0 ] ;
47
+ T result ;
48
+
49
+ try {
50
+ result = Activator . CreateInstance < T > ( ) ;
51
+ }
52
+ catch ( MissingMethodException ) {
53
+ throw new InvalidOperationException ( message : "The type must contain a public, parameterless constructor." ) ;
28
54
}
29
- }
30
55
31
- public SupportsContentType SupportsContentType {
32
- get {
33
- return x => Array . IndexOf ( AcceptedContentTypes , x ) != - 1 || x . Contains ( "csv" ) ;
56
+ var method = typeof ( T ) . GetMethod ( name : "Add" ) ;
57
+
58
+ if ( method == null ) {
59
+ throw new InvalidOperationException (
60
+ message : "If the type implements IEnumerable<T>, then it must contain a public \" Add(T)\" method."
61
+ ) ;
34
62
}
35
- }
36
63
37
- public DataFormat DataFormat {
38
- get {
39
- return DataFormat . None ;
64
+ foreach ( var record in csvReader . GetRecords ( itemType ) ) {
65
+ method . Invoke ( result , new [ ] { record } ) ;
40
66
}
67
+
68
+ return result ;
69
+ }
70
+ catch ( Exception exception ) {
71
+ throw new DeserializationException ( response , exception ) ;
41
72
}
73
+ }
42
74
43
- public string ContentType { get ; set ; } = TextCsvContentType ;
75
+ public string ? Serialize ( Parameter parameter ) => Serialize ( parameter . Value ) ;
44
76
45
- public CsvHelperSerializer ( ) {
46
- _configuration = new CsvConfiguration ( CultureInfo . InvariantCulture ) ;
77
+ public string ? Serialize ( object ? obj ) {
78
+ if ( obj == null ) {
79
+ return null ;
47
80
}
48
81
49
- public CsvHelperSerializer ( CsvConfiguration configuration ) {
50
- _configuration = configuration ;
51
- }
82
+ using var stringWriter = new StringWriter ( ) ;
52
83
53
- public T ? Deserialize < T > ( RestResponse response ) {
54
- try {
55
- if ( response . Content == null ) {
56
- throw new InvalidOperationException ( message : "Response content is null" ) ;
57
- }
58
- else {
59
- using ( StringReader stringReader = new StringReader ( response . Content ) )
60
- using ( CsvReader csvReader = new CsvReader ( stringReader , CultureInfo . CurrentCulture ) ) {
61
- Type ? @interface = typeof ( T ) . GetInterface ( "IEnumerable`1" ) ;
62
-
63
- if ( @interface == null ) {
64
- csvReader . Read ( ) ;
65
-
66
- return csvReader . GetRecord < T > ( ) ;
67
- }
68
- else {
69
- Type itemType = @interface . GenericTypeArguments [ 0 ] ;
70
- T result ;
71
-
72
- try {
73
- result = Activator . CreateInstance < T > ( ) ;
74
- }
75
- catch ( MissingMethodException ) {
76
- throw new InvalidOperationException ( message : "The type must contain a public, parameterless constructor." ) ;
77
- }
78
-
79
- MethodInfo ? method = typeof ( T ) . GetMethod ( name : "Add" ) ;
80
-
81
- if ( method == null ) {
82
- throw new InvalidOperationException ( message : "If the type implements IEnumerable<T>, then it must contain a public \" Add(T)\" method." ) ;
83
- }
84
- else {
85
- foreach ( object record in csvReader . GetRecords ( itemType ) ) {
86
- method . Invoke ( result , new object [ ]
87
- {
88
- record
89
- } ) ;
90
- }
91
- }
92
-
93
- return result ;
94
- }
95
- }
96
- }
97
- }
98
- catch ( Exception exception ) {
99
- throw new DeserializationException ( response , exception ) ;
100
- }
101
- }
84
+ using var csvWriter = new CsvWriter ( stringWriter , _configuration ) ;
102
85
103
- public string ? Serialize ( Parameter parameter ) {
104
- return Serialize ( parameter . Value ) ;
105
- }
86
+ if ( obj is IEnumerable records ) {
87
+ // ReSharper disable once PossibleMultipleEnumeration
88
+ var enumerator = records . GetEnumerator ( ) ;
106
89
107
- public string ? Serialize ( object ? obj ) {
108
- if ( obj == null ) {
109
- return null ;
90
+ if ( enumerator . MoveNext ( ) && enumerator . Current != null ) {
91
+ csvWriter . WriteHeader ( enumerator . Current . GetType ( ) ) ;
92
+ csvWriter . NextRecord ( ) ;
93
+ // ReSharper disable once PossibleMultipleEnumeration
94
+ csvWriter . WriteRecords ( records ) ;
110
95
}
111
- else {
112
- using ( StringWriter stringWriter = new StringWriter ( ) )
113
- using ( CsvWriter csvWriter = new CsvWriter ( stringWriter , _configuration ) ) {
114
- if ( obj is IEnumerable records ) {
115
- IEnumerator enumerator = records . GetEnumerator ( ) ;
116
-
117
- if ( enumerator . MoveNext ( ) ) {
118
- csvWriter . WriteHeader ( enumerator . Current . GetType ( ) ) ;
119
- csvWriter . NextRecord ( ) ;
120
- csvWriter . WriteRecords ( records ) ;
121
- }
122
-
123
- if ( enumerator is IDisposable disposable ) {
124
- disposable . Dispose ( ) ;
125
- }
126
- }
127
- else {
128
- csvWriter . WriteHeader ( obj . GetType ( ) ) ;
129
- csvWriter . NextRecord ( ) ;
130
- csvWriter . WriteRecord ( obj ) ;
131
- csvWriter . NextRecord ( ) ;
132
- }
133
-
134
- return stringWriter . ToString ( ) ;
135
- }
96
+
97
+ if ( enumerator is IDisposable disposable ) {
98
+ disposable . Dispose ( ) ;
136
99
}
137
100
}
101
+ else {
102
+ csvWriter . WriteHeader ( obj . GetType ( ) ) ;
103
+ csvWriter . NextRecord ( ) ;
104
+ csvWriter . WriteRecord ( obj ) ;
105
+ csvWriter . NextRecord ( ) ;
106
+ }
107
+
108
+ return stringWriter . ToString ( ) ;
138
109
}
139
- }
110
+ }
0 commit comments