44
55using System ;
66using System . Collections ;
7- using System . Runtime . Serialization ;
7+ using System . Globalization ;
88using System . Text ;
9+
910using Elastic . Transport . Extensions ;
1011
1112namespace Elastic . Transport ;
1213
1314/// <summary>
1415/// 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.
1617/// </summary>
1718public sealed class UrlFormatter : IFormatProvider , ICustomFormatter
1819{
@@ -39,26 +40,32 @@ public string Format(string? format, object? arg, IFormatProvider? formatProvide
3940 public object ? GetFormat ( Type formatType ) => formatType == typeof ( ICustomFormatter ) ? this : null ;
4041
4142 /// <inheritdoc cref="CreateString(object, ITransportConfiguration)"/>
42- public string ? CreateString ( object ? value ) => CreateString ( value , _settings ) ;
43+ public string CreateString ( object ? value ) => CreateString ( value , _settings ) ;
4344
4445 /// <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 ) =>
4647 value switch
4748 {
48- null => null ,
49+ null => string . Empty ,
4950 string s => s ,
5051 string [ ] ss => string . Join ( "," , ss ) ,
5152 Enum e => e . GetStringValue ( ) ,
5253 bool b => b ? "true" : "false" ,
5354 DateTimeOffset offset => offset . ToString ( "o" ) ,
5455 TimeSpan timeSpan => timeSpan . ToTimeUnit ( ) ,
56+ // Custom `IUrlParameter.GetString()` implementations should take precedence over collection
57+ // specializations.
58+ IUrlParameter urlParam => urlParam . GetString ( settings ) ,
5559 // Special handling to support non-zero based arrays
5660 Array pns => CreateStringFromArray ( pns , settings ) ,
5761 // Performance optimization for directly indexable collections
5862 IList pns => CreateStringFromIList ( pns , settings ) ,
5963 // Generic implementation for all other collections
6064 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
6269 } ;
6370
6471 private static string CreateStringFromArray ( Array value , ITransportConfiguration settings )
@@ -67,8 +74,9 @@ private static string CreateStringFromArray(Array value, ITransportConfiguration
6774 {
6875 case 0 :
6976 return string . Empty ;
77+
7078 case 1 :
71- return ResolveUrlParameterOrDefault ( value . GetValue ( value . GetLowerBound ( 0 ) ) , settings ) ;
79+ return CreateString ( value . GetValue ( value . GetLowerBound ( 0 ) ) , settings ) ;
7280 }
7381
7482 var sb = new StringBuilder ( ) ;
@@ -78,7 +86,7 @@ private static string CreateStringFromArray(Array value, ITransportConfiguration
7886 if ( sb . Length != 0 )
7987 sb . Append ( ',' ) ;
8088
81- sb . Append ( ResolveUrlParameterOrDefault ( value . GetValue ( i ) , settings ) ) ;
89+ sb . Append ( CreateString ( value . GetValue ( i ) , settings ) ) ;
8290 }
8391
8492 return sb . ToString ( ) ;
@@ -90,8 +98,9 @@ private static string CreateStringFromIList(IList value, ITransportConfiguration
9098 {
9199 case 0 :
92100 return string . Empty ;
101+
93102 case 1 :
94- return ResolveUrlParameterOrDefault ( value [ 0 ] , settings ) ;
103+ return CreateString ( value [ 0 ] , settings ) ;
95104 }
96105
97106 var sb = new StringBuilder ( ) ;
@@ -101,7 +110,7 @@ private static string CreateStringFromIList(IList value, ITransportConfiguration
101110 if ( sb . Length != 0 )
102111 sb . Append ( ',' ) ;
103112
104- sb . Append ( ResolveUrlParameterOrDefault ( value [ i ] , settings ) ) ;
113+ sb . Append ( CreateString ( value [ i ] , settings ) ) ;
105114 }
106115
107116 return sb . ToString ( ) ;
@@ -116,36 +125,9 @@ private static string CreateStringFromIEnumerable(IEnumerable value, ITransportC
116125 if ( sb . Length != 0 )
117126 sb . Append ( ',' ) ;
118127
119- sb . Append ( ResolveUrlParameterOrDefault ( v , settings ) ) ;
128+ sb . Append ( CreateString ( v , settings ) ) ;
120129 }
121130
122131 return sb . ToString ( ) ;
123132 }
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- }
151133}
0 commit comments