Fixed cache logic inside of RequestParams, fixes #458

This commit is contained in:
Jonas Dellinger 2020-06-09 03:04:51 +02:00
parent 3e0c4e479b
commit 208b90fb56
2 changed files with 77 additions and 12 deletions

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using NUnit.Framework;
namespace SpotifyAPI.Web.Tests
{
[TestFixture]
public class RequestParamsTest
{
[Test]
public void CacheDoesNotInterfereQuery()
{
var first = new FirstRequestModel { First = true };
var firstParams = first.BuildQueryParams();
var second = new SecondRequestModel { Second = false };
var secondParams = second.BuildQueryParams();
Assert.AreEqual(1, firstParams.Keys.Count);
Assert.AreEqual("true", firstParams["first"]);
Assert.AreEqual(1, secondParams.Keys.Count);
Assert.AreEqual("false", secondParams["second"]);
}
[Test]
public void CacheDoesNotInterfereBody()
{
var first = new FirstRequestModel { First = true };
var firstParams = first.BuildBodyParams();
var second = new SecondRequestModel { Second = false };
var secondParams = second.BuildBodyParams();
Assert.AreEqual("{\"first\":true}", firstParams.ToString(Formatting.None));
Assert.AreEqual("{\"second\":false}", secondParams.ToString(Formatting.None));
}
}
public class FirstRequestModel : RequestParams
{
[BodyParam("first")]
[QueryParam("first")]
public bool? First { get; set; }
}
public class SecondRequestModel : RequestParams
{
[BodyParam("second")]
[QueryParam("second")]
public bool? Second { get; set; }
}
}

View File

@ -10,19 +10,22 @@ namespace SpotifyAPI.Web
{ {
public abstract class RequestParams public abstract class RequestParams
{ {
private static readonly ConcurrentDictionary<PropertyInfo, BodyParamAttribute> _bodyParamsCache = private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>> _bodyParamsCache =
new ConcurrentDictionary<PropertyInfo, BodyParamAttribute>(); new ConcurrentDictionary<Type, List<(PropertyInfo, BodyParamAttribute)>>();
public JObject BuildBodyParams() public JObject BuildBodyParams()
{ {
// Make sure everything is okay before building body params // Make sure everything is okay before building body params
CustomEnsure(); CustomEnsure();
var body = new JObject(); var body = new JObject();
if (!_bodyParamsCache.IsEmpty) var type = GetType();
if (!_bodyParamsCache.IsEmpty && _bodyParamsCache.ContainsKey(type))
{ {
foreach (var bodyParam in _bodyParamsCache) foreach (var (info, attribute) in _bodyParamsCache[type])
{ {
AddBodyParam(body, bodyParam.Key, bodyParam.Value); AddBodyParam(body, info, attribute);
} }
} }
else else
@ -31,10 +34,11 @@ namespace SpotifyAPI.Web
.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) .GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0); .Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
_bodyParamsCache[type] = new List<(PropertyInfo, BodyParamAttribute)>();
foreach (var prop in bodyProps) foreach (var prop in bodyProps)
{ {
var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute)); var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
_bodyParamsCache[prop] = attribute; _bodyParamsCache[type].Add((prop, attribute));
AddBodyParam(body, prop, attribute); AddBodyParam(body, prop, attribute);
} }
} }
@ -51,20 +55,22 @@ namespace SpotifyAPI.Web
} }
} }
private static readonly ConcurrentDictionary<PropertyInfo, QueryParamAttribute> _queryParamsCache = private static readonly ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>> _queryParamsCache =
new ConcurrentDictionary<PropertyInfo, QueryParamAttribute>(); new ConcurrentDictionary<Type, List<(PropertyInfo, QueryParamAttribute)>>();
public Dictionary<string, string> BuildQueryParams() public Dictionary<string, string> BuildQueryParams()
{ {
// Make sure everything is okay before building query params // Make sure everything is okay before building query params
CustomEnsure(); CustomEnsure();
var queryParams = new Dictionary<string, string>(); var queryParams = new Dictionary<string, string>();
var type = GetType();
if (!_queryParamsCache.IsEmpty) if (!_queryParamsCache.IsEmpty && _queryParamsCache.ContainsKey(type))
{ {
foreach (var queryParam in _queryParamsCache) foreach (var (info, attribute) in _queryParamsCache[type])
{ {
AddQueryParam(queryParams, queryParam.Key, queryParam.Value); AddQueryParam(queryParams, info, attribute);
} }
} }
else else
@ -72,10 +78,11 @@ namespace SpotifyAPI.Web
var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0); .Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0);
_queryParamsCache[type] = new List<(PropertyInfo, QueryParamAttribute)>();
foreach (var prop in queryProps) foreach (var prop in queryProps)
{ {
var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute)); var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
_queryParamsCache[prop] = attribute; _queryParamsCache[type].Add((prop, attribute));
AddQueryParam(queryParams, prop, attribute); AddQueryParam(queryParams, prop, attribute);
} }
} }
@ -95,6 +102,10 @@ namespace SpotifyAPI.Web
var str = string.Join(",", list); var str = string.Join(",", list);
queryParams.Add(attribute.Key ?? prop.Name, str); queryParams.Add(attribute.Key ?? prop.Name, str);
} }
else if (value is bool valueAsBool)
{
queryParams.Add(attribute.Key ?? prop.Name, valueAsBool ? "true" : "false");
}
else if (value is Enum valueAsEnum) else if (value is Enum valueAsEnum)
{ {
var enumType = valueAsEnum.GetType(); var enumType = valueAsEnum.GetType();