Skip to content

Commit 0ef07be

Browse files
committed
Added Reflection Cache for RequestParams JohnnyCrazy#451
1 parent f105fcb commit 0ef07be

3 files changed

Lines changed: 98 additions & 41 deletions

File tree

‎SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ private static async Task Start()
6262
var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers());
6363
Console.WriteLine($"Total Playlists in your Account: {playlists.Count}");
6464

65+
_server.Dispose();
6566
Environment.Exit(0);
6667
}
6768

‎SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ namespace SpotifyAPI.Web
44
{
55
public interface IOAuthClient
66
{
7+
/// <summary>
8+
/// Requests a new token using client_ids and client_secrets.
9+
/// If the token is expired, simply call the funtion again to get a new token
10+
/// </summary>
11+
/// <param name="request"></param>
12+
/// <returns></returns>
713
Task<CredentialsTokenResponse> RequestToken(ClientCredentialsRequest request);
14+
15+
/// <summary>
16+
/// Refresh an already received token via Authorization Code Auth
17+
/// </summary>
18+
/// <param name="request"></param>
19+
/// <returns></returns>
20+
Task<AuthorizationCodeRefreshResponse> RequestToken(AuthorizationCodeRefreshRequest request);
21+
Task<AuthorizationCodeTokenResponse> RequestToken(AuthorizationCodeTokenRequest request);
822
}
923
}

‎SpotifyAPI.Web/Models/Request/RequestParams.cs‎

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Concurrent;
12
using System.Reflection;
23
using System;
34
using System.Linq;
@@ -9,75 +10,116 @@ namespace SpotifyAPI.Web
910
{
1011
public abstract class RequestParams
1112
{
13+
private static readonly ConcurrentDictionary<PropertyInfo, BodyParamAttribute> _bodyParamsCache =
14+
new ConcurrentDictionary<PropertyInfo, BodyParamAttribute>();
1215
public JObject BuildBodyParams()
1316
{
1417
// Make sure everything is okay before building body params
1518
CustomEnsure();
1619

17-
var bodyProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
18-
.Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
19-
20-
var obj = new JObject();
21-
foreach (var prop in bodyProps)
20+
var body = new JObject();
21+
if (!_bodyParamsCache.IsEmpty)
22+
{
23+
foreach (var bodyParam in _bodyParamsCache)
24+
{
25+
AddBodyParam(body, bodyParam.Key, bodyParam.Value);
26+
}
27+
}
28+
else
2229
{
23-
object value = prop.GetValue(this);
24-
if (value != null && prop.GetCustomAttribute(typeof(BodyParamAttribute)) is BodyParamAttribute attribute)
30+
var bodyProps = GetType()
31+
.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
32+
.Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0);
33+
34+
foreach (var prop in bodyProps)
2535
{
26-
obj[attribute.Key ?? prop.Name] = JToken.FromObject(value);
36+
var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
37+
_bodyParamsCache[prop] = attribute;
38+
AddBodyParam(body, prop, attribute);
2739
}
2840
}
29-
return obj;
41+
42+
return body;
43+
}
44+
45+
private void AddBodyParam(JObject body, PropertyInfo prop, BodyParamAttribute attribute)
46+
{
47+
object value = prop.GetValue(this);
48+
if (value != null)
49+
{
50+
body[attribute.Key ?? prop.Name] = JToken.FromObject(value);
51+
}
3052
}
3153

54+
private static readonly ConcurrentDictionary<PropertyInfo, QueryParamAttribute> _queryParamsCache =
55+
new ConcurrentDictionary<PropertyInfo, QueryParamAttribute>();
3256
public Dictionary<string, string> BuildQueryParams()
3357
{
3458
// Make sure everything is okay before building query params
3559
CustomEnsure();
3660

37-
var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
61+
var queryParams = new Dictionary<string, string>();
62+
63+
if (!_queryParamsCache.IsEmpty)
64+
{
65+
foreach (var queryParam in _queryParamsCache)
66+
{
67+
AddQueryParam(queryParams, queryParam.Key, queryParam.Value);
68+
}
69+
}
70+
else
71+
{
72+
var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public)
3873
.Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0);
3974

40-
var queryParams = new Dictionary<string, string>();
41-
foreach (var prop in queryProps)
75+
foreach (var prop in queryProps)
76+
{
77+
var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
78+
_queryParamsCache[prop] = attribute;
79+
AddQueryParam(queryParams, prop, attribute);
80+
}
81+
}
82+
83+
AddCustomQueryParams(queryParams);
84+
85+
return queryParams;
86+
}
87+
88+
private void AddQueryParam(Dictionary<string, string> queryParams, PropertyInfo prop, QueryParamAttribute attribute)
89+
{
90+
object value = prop.GetValue(this);
91+
if (value != null)
4292
{
43-
object value = prop.GetValue(this);
44-
if (value != null && prop.GetCustomAttribute(typeof(QueryParamAttribute)) is QueryParamAttribute attribute)
93+
if (value is IList<string> list && list.Count > 0)
4594
{
46-
if (value is IList<string> list && list.Count > 0)
47-
{
48-
var str = string.Join(",", list);
49-
queryParams.Add(attribute.Key ?? prop.Name, str);
50-
}
51-
else if (value is Enum valueAsEnum)
52-
{
53-
var enumType = valueAsEnum.GetType();
54-
var valueList = new List<string>();
95+
var str = string.Join(",", list);
96+
queryParams.Add(attribute.Key ?? prop.Name, str);
97+
}
98+
else if (value is Enum valueAsEnum)
99+
{
100+
var enumType = valueAsEnum.GetType();
101+
var valueList = new List<string>();
55102

56-
foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType()))
103+
foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType()))
104+
{
105+
if (valueAsEnum.HasFlag(enumVal))
57106
{
58-
if (valueAsEnum.HasFlag(enumVal))
107+
if (enumType
108+
.GetMember(enumVal.ToString())[0]
109+
.GetCustomAttributes(typeof(StringAttribute))
110+
.FirstOrDefault() is StringAttribute stringAttr)
59111
{
60-
if (enumType
61-
.GetMember(enumVal.ToString())[0]
62-
.GetCustomAttributes(typeof(StringAttribute))
63-
.FirstOrDefault() is StringAttribute stringAttr)
64-
{
65-
valueList.Add(stringAttr.Value);
66-
}
112+
valueList.Add(stringAttr.Value);
67113
}
68114
}
69-
queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList));
70-
}
71-
else
72-
{
73-
queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
74115
}
116+
queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList));
117+
}
118+
else
119+
{
120+
queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
75121
}
76122
}
77-
78-
AddCustomQueryParams(queryParams);
79-
80-
return queryParams;
81123
}
82124

83125
protected virtual void CustomEnsure() { }

0 commit comments

Comments
 (0)