4
4
5
5
using System ;
6
6
using System . Collections ;
7
- using System . Runtime . Serialization ;
7
+ using System . Globalization ;
8
8
using System . Text ;
9
+
9
10
using Elastic . Transport . Extensions ;
10
11
11
12
namespace Elastic . Transport ;
12
13
13
14
/// <summary>
14
15
/// A formatter that can utilize <see cref="ITransportConfiguration" /> to resolve <see cref="IUrlParameter" />'s passed
15
- /// as format arguments. It also handles known string representations for e.g bool/Enums/IEnumerable.
16
+ /// as format arguments. It also handles known string representations for e.g. bool/Enums/IEnumerable.
16
17
/// </summary>
17
18
public sealed class UrlFormatter : IFormatProvider , ICustomFormatter
18
19
{
@@ -39,26 +40,32 @@ public string Format(string? format, object? arg, IFormatProvider? formatProvide
39
40
public object ? GetFormat ( Type formatType ) => formatType == typeof ( ICustomFormatter ) ? this : null ;
40
41
41
42
/// <inheritdoc cref="CreateString(object, ITransportConfiguration)"/>
42
- public string ? CreateString ( object ? value ) => CreateString ( value , _settings ) ;
43
+ public string CreateString ( object ? value ) => CreateString ( value , _settings ) ;
43
44
44
45
/// <summary> Creates a query string representation for <paramref name="value"/> </summary>
45
- public static string ? CreateString ( object ? value , ITransportConfiguration settings ) =>
46
+ public static string CreateString ( object ? value , ITransportConfiguration settings ) =>
46
47
value switch
47
48
{
48
- null => null ,
49
+ null => string . Empty ,
49
50
string s => s ,
50
51
string [ ] ss => string . Join ( "," , ss ) ,
51
52
Enum e => e . GetStringValue ( ) ,
52
53
bool b => b ? "true" : "false" ,
53
54
DateTimeOffset offset => offset . ToString ( "o" ) ,
54
55
TimeSpan timeSpan => timeSpan . ToTimeUnit ( ) ,
56
+ // Custom `IUrlParameter.GetString()` implementations should take precedence over collection
57
+ // specializations.
58
+ IUrlParameter urlParam => urlParam . GetString ( settings ) ,
55
59
// Special handling to support non-zero based arrays
56
60
Array pns => CreateStringFromArray ( pns , settings ) ,
57
61
// Performance optimization for directly indexable collections
58
62
IList pns => CreateStringFromIList ( pns , settings ) ,
59
63
// Generic implementation for all other collections
60
64
IEnumerable pns => CreateStringFromIEnumerable ( pns , settings ) ,
61
- _ => ResolveUrlParameterOrDefault ( value , settings )
65
+ // Generic implementation for `IFormattable` types
66
+ IFormattable f => f . ToString ( null , CultureInfo . InvariantCulture ) ,
67
+ // Last resort fallback
68
+ _ => value . ToString ( ) ?? string . Empty
62
69
} ;
63
70
64
71
private static string CreateStringFromArray ( Array value , ITransportConfiguration settings )
@@ -67,8 +74,9 @@ private static string CreateStringFromArray(Array value, ITransportConfiguration
67
74
{
68
75
case 0 :
69
76
return string . Empty ;
77
+
70
78
case 1 :
71
- return ResolveUrlParameterOrDefault ( value . GetValue ( value . GetLowerBound ( 0 ) ) , settings ) ;
79
+ return CreateString ( value . GetValue ( value . GetLowerBound ( 0 ) ) , settings ) ;
72
80
}
73
81
74
82
var sb = new StringBuilder ( ) ;
@@ -78,7 +86,7 @@ private static string CreateStringFromArray(Array value, ITransportConfiguration
78
86
if ( sb . Length != 0 )
79
87
sb . Append ( ',' ) ;
80
88
81
- sb . Append ( ResolveUrlParameterOrDefault ( value . GetValue ( i ) , settings ) ) ;
89
+ sb . Append ( CreateString ( value . GetValue ( i ) , settings ) ) ;
82
90
}
83
91
84
92
return sb . ToString ( ) ;
@@ -90,8 +98,9 @@ private static string CreateStringFromIList(IList value, ITransportConfiguration
90
98
{
91
99
case 0 :
92
100
return string . Empty ;
101
+
93
102
case 1 :
94
- return ResolveUrlParameterOrDefault ( value [ 0 ] , settings ) ;
103
+ return CreateString ( value [ 0 ] , settings ) ;
95
104
}
96
105
97
106
var sb = new StringBuilder ( ) ;
@@ -101,7 +110,7 @@ private static string CreateStringFromIList(IList value, ITransportConfiguration
101
110
if ( sb . Length != 0 )
102
111
sb . Append ( ',' ) ;
103
112
104
- sb . Append ( ResolveUrlParameterOrDefault ( value [ i ] , settings ) ) ;
113
+ sb . Append ( CreateString ( value [ i ] , settings ) ) ;
105
114
}
106
115
107
116
return sb . ToString ( ) ;
@@ -116,36 +125,9 @@ private static string CreateStringFromIEnumerable(IEnumerable value, ITransportC
116
125
if ( sb . Length != 0 )
117
126
sb . Append ( ',' ) ;
118
127
119
- sb . Append ( ResolveUrlParameterOrDefault ( v , settings ) ) ;
128
+ sb . Append ( CreateString ( v , settings ) ) ;
120
129
}
121
130
122
131
return sb . ToString ( ) ;
123
132
}
124
-
125
- private static string ResolveUrlParameterOrDefault ( object ? value , ITransportConfiguration settings ) =>
126
- value switch
127
- {
128
- null => string . Empty ,
129
- IUrlParameter urlParam => urlParam . GetString ( settings ) ,
130
- _ => GetEnumMemberName ( value ) ?? value . ToString ( ) ?? string . Empty
131
- } ;
132
-
133
- private static string ? GetEnumMemberName ( object value )
134
- {
135
- var type = value . GetType ( ) ;
136
- if ( ! type . IsEnum )
137
- return null ;
138
-
139
- var name = Enum . GetName ( type , value ) ;
140
- if ( name is null )
141
- return null ;
142
-
143
- var field = type . GetField ( name ) ;
144
- if ( field is null )
145
- return null ;
146
-
147
- return Attribute . GetCustomAttribute ( field , typeof ( EnumMemberAttribute ) ) is EnumMemberAttribute attribute
148
- ? attribute . Value
149
- : null ;
150
- }
151
133
}
0 commit comments