22using CsvHelper . Configuration ;
33using System . Collections ;
44using System . Globalization ;
5- using System . Reflection ;
65
7- namespace RestSharp . Serializers . CsvHelper {
8- public class CsvHelperSerializer : IDeserializer , IRestSerializer , ISerializer {
9- private const string TextCsvContentType = "text/csv" ;
6+ namespace RestSharp . Serializers . CsvHelper ;
107
11- private readonly CsvConfiguration _configuration ;
8+ public class CsvHelperSerializer : IDeserializer , IRestSerializer , ISerializer {
9+ const string TextCsvContentType = "text/csv" ;
1210
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 ) ;
1826
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 > ( ) ;
2244 }
23- }
2445
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." ) ;
2854 }
29- }
3055
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+ ) ;
3462 }
35- }
3663
37- public DataFormat DataFormat {
38- get {
39- return DataFormat . None ;
64+ foreach ( var record in csvReader . GetRecords ( itemType ) ) {
65+ method . Invoke ( result , new [ ] { record } ) ;
4066 }
67+
68+ return result ;
69+ }
70+ catch ( Exception exception ) {
71+ throw new DeserializationException ( response , exception ) ;
4172 }
73+ }
4274
43- public string ContentType { get ; set ; } = TextCsvContentType ;
75+ public string ? Serialize ( Parameter parameter ) => Serialize ( parameter . Value ) ;
4476
45- public CsvHelperSerializer ( ) {
46- _configuration = new CsvConfiguration ( CultureInfo . InvariantCulture ) ;
77+ public string ? Serialize ( object ? obj ) {
78+ if ( obj == null ) {
79+ return null ;
4780 }
4881
49- public CsvHelperSerializer ( CsvConfiguration configuration ) {
50- _configuration = configuration ;
51- }
82+ using var stringWriter = new StringWriter ( ) ;
5283
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 ) ;
10285
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 ( ) ;
10689
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 ) ;
11095 }
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 ( ) ;
13699 }
137100 }
101+ else {
102+ csvWriter . WriteHeader ( obj . GetType ( ) ) ;
103+ csvWriter . NextRecord ( ) ;
104+ csvWriter . WriteRecord ( obj ) ;
105+ csvWriter . NextRecord ( ) ;
106+ }
107+
108+ return stringWriter . ToString ( ) ;
138109 }
139- }
110+ }
0 commit comments