1
+ using System ;
2
+ using System . Collections ;
3
+ using System . Collections . Generic ;
4
+ using System . Globalization ;
5
+ using System . Linq ;
6
+ using System . Reflection ;
7
+
8
+ namespace Flurl . Util
9
+ {
10
+ public static class CommonExtensions
11
+ {
12
+ /// <summary>
13
+ /// Converts an object's public properties to a collection of string-based key-value pairs. If the object happens
14
+ /// to be an IDictionary, the IDictionary's keys and values converted to strings and returned.
15
+ /// </summary>
16
+ /// <param name="obj">The object to parse into key-value pairs</param>
17
+ /// <returns></returns>
18
+ public static IEnumerable < KeyValuePair < string , object > > ToKeyValuePairs ( this object obj )
19
+ {
20
+ if ( obj == null )
21
+ throw new ArgumentNullException ( nameof ( obj ) ) ;
22
+
23
+ return
24
+ ( obj is string ) ? QueryParamCollection . Parse ( ( string ) obj ) :
25
+ ( obj is IEnumerable ) ? CollectionToKV ( ( IEnumerable ) obj ) :
26
+ ObjectToKV ( obj ) ;
27
+ }
28
+
29
+ /// <summary>
30
+ /// Returns a string that represents the current object, using CultureInfo.InvariantCulture where possible.
31
+ /// </summary>
32
+ public static string ToInvariantString ( this object obj )
33
+ {
34
+ // inspired by: http://stackoverflow.com/a/19570016/62600
35
+
36
+ var c = obj as IConvertible ;
37
+ if ( c != null )
38
+ return c . ToString ( CultureInfo . InvariantCulture ) ;
39
+
40
+ var f = obj as IFormattable ;
41
+ return f ? . ToString ( null , CultureInfo . InvariantCulture ) ?? obj . ToString ( ) ;
42
+ }
43
+
44
+ private static IEnumerable < KeyValuePair < string , object > > ObjectToKV ( object obj )
45
+ {
46
+ return from prop in obj . GetType ( ) . GetProperties ( )
47
+ let val = prop . GetValue ( obj , null )
48
+ select new KeyValuePair < string , object > ( prop . Name , val ) ;
49
+ }
50
+
51
+ private static IEnumerable < KeyValuePair < string , object > > CollectionToKV ( IEnumerable col )
52
+ {
53
+ // Accepts KeyValuePairs or any aribitray types that contain a property called "Key" or "Name" and a property called "Value".
54
+ foreach ( var item in col )
55
+ {
56
+ if ( item == null )
57
+ continue ;
58
+
59
+ var type = item . GetType ( ) ;
60
+ var keyProp = type . GetProperty ( "Key" ) ?? type . GetProperty ( "key" ) ?? type . GetProperty ( "Name" ) ?? type . GetProperty ( "name" ) ;
61
+ if ( keyProp == null )
62
+ throw new ArgumentException ( "Cannot parse " + type . Name + " to key-value pair. Type must contain a property called 'Key' or 'Name'." ) ;
63
+
64
+ var valProp = type . GetProperty ( "Value" ) ?? type . GetProperty ( "value" ) ;
65
+ if ( valProp == null )
66
+ throw new ArgumentException ( "Cannot parse " + type . Name + " to key-value pair. Type must contain a property called 'Value'." ) ;
67
+
68
+ var key = keyProp . GetValue ( item , null ) ;
69
+ if ( key == null )
70
+ continue ;
71
+
72
+ var val = valProp . GetValue ( item , null ) ;
73
+ yield return new KeyValuePair < string , object > ( key . ToInvariantString ( ) , val ) ;
74
+ }
75
+ }
76
+ }
77
+ }
0 commit comments