Skip to content

Commit

Permalink
Merge pull request #113 from dragonfruitnetwork/non-string-ienumerable
Browse files Browse the repository at this point in the history
add support for non-string enumerables
  • Loading branch information
aspriddell authored Mar 24, 2022
2 parents 5c8c86a + 080f53b commit 993fc15
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
33 changes: 12 additions & 21 deletions src/Utils/ParameterUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ internal static IEnumerable<KeyValuePair<string, string>> GetParameter<T>(object
// check if the type we've got is an IEnumerable of anything AND we have a valid collection handler mode
if (attribute.CollectionHandling.HasValue && typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
Func<IEnumerable<object>, string, CultureInfo, IEnumerable<KeyValuePair<string, string>>> entityConverter = attribute.CollectionHandling switch
Func<IEnumerable, IEnumerable<KeyValuePair<string, string>>> entityConverter = attribute.CollectionHandling switch
{
CollectionConversionMode.Recursive => ApplyRecursiveConversion,
CollectionConversionMode.Unordered => ApplyUnorderedConversion,
CollectionConversionMode.Ordered => ApplyOrderedConversion,
CollectionConversionMode.Concatenated => (a, b, c) => ApplyConcatenation(a, b, c, attribute.CollectionSeparator ?? DefaultConcatenationCharacter),
CollectionConversionMode.Ordered => values => ApplyOrderedConversion(values, keyName, culture),
CollectionConversionMode.Recursive => values => values.Cast<object>().Select(x => x.ToKeyValuePair(keyName, culture)),
CollectionConversionMode.Unordered => values => values.Cast<object>().Select(x => x.ToKeyValuePair($"{keyName}[]", culture)),
CollectionConversionMode.Concatenated => values => ApplyConcatenation(values, keyName, culture, attribute.CollectionSeparator ?? DefaultConcatenationCharacter),

_ => throw new ArgumentOutOfRangeException()
};

foreach (var entry in entityConverter.Invoke((IEnumerable<object>)propertyValue, keyName, culture))
// we purposely keep nulls in here, as it might affect the ordering.
// we purposely keep nulls in here, as it might affect the ordering.
foreach (var entry in entityConverter.Invoke((IEnumerable)propertyValue))
{
yield return entry;
}
Expand Down Expand Up @@ -102,17 +102,7 @@ internal static object GetSingleParameterObject<T>(object host) where T : Attrib
return attributedProperty.GetValue(host);
}

private static IEnumerable<KeyValuePair<string, string>> ApplyRecursiveConversion(IEnumerable<object> values, string keyName, CultureInfo culture)
{
return values.Select(x => x.ToKeyValuePair(keyName, culture));
}

private static IEnumerable<KeyValuePair<string, string>> ApplyUnorderedConversion(IEnumerable<object> values, string keyName, CultureInfo culture)
{
return values.Select(x => x.ToKeyValuePair($"{keyName}[]", culture));
}

private static IEnumerable<KeyValuePair<string, string>> ApplyOrderedConversion(IEnumerable<object> values, string keyName, CultureInfo culture)
private static IEnumerable<KeyValuePair<string, string>> ApplyOrderedConversion(IEnumerable values, string keyName, CultureInfo culture)
{
var counter = 0;
var enumerator = values.GetEnumerator();
Expand All @@ -122,12 +112,13 @@ private static IEnumerable<KeyValuePair<string, string>> ApplyOrderedConversion(
yield return enumerator.Current.ToKeyValuePair($"{keyName}[{counter++}]", culture);
}

enumerator.Dispose();
// dispose if possible
(enumerator as IDisposable)?.Dispose();
}

private static IEnumerable<KeyValuePair<string, string>> ApplyConcatenation(IEnumerable<object> values, string keyName, CultureInfo culture, string concatCharacter)
private static IEnumerable<KeyValuePair<string, string>> ApplyConcatenation(IEnumerable values, string keyName, CultureInfo culture, string concatCharacter)
{
yield return new KeyValuePair<string, string>(keyName, string.Join(concatCharacter, values.Select(x => x.AsString(culture))));
yield return new KeyValuePair<string, string>(keyName, string.Join(concatCharacter, values.Cast<object>().Select(x => x.AsString(culture))));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
23 changes: 23 additions & 0 deletions tests/Requests/RequestTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// DragonFruit.Data Copyright DragonFruit Network
// Licensed under the MIT License. Please refer to the LICENSE file at the root of this project for details

using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using DragonFruit.Data.Basic;
using DragonFruit.Data.Parameters;
using NUnit.Framework;

namespace DragonFruit.Data.Tests.Requests
Expand Down Expand Up @@ -48,5 +51,25 @@ public void TestSyncHttp2Request()
Assert.IsTrue(result.IsSuccessStatusCode);
Assert.AreEqual(request.Version, result.Version);
}

[Test]
public void TestConcatEnumerable()
{
var req = new EnumerableTest(Enumerable.Range(1, 5));
Assert.True(req.FullUrl.Contains("1,2,3"));
}

private class EnumerableTest : ApiRequest
{
public override string Path => "https://example.com";

public EnumerableTest(IEnumerable<int> data)
{
Data = data;
}

[QueryParameter("data", CollectionConversionMode.Concatenated)]
public IEnumerable<int> Data { get; set; }
}
}
}

0 comments on commit 993fc15

Please sign in to comment.