From 0ef07bed0bcb7aee312bbdc234d89bbf8c3c2276 Mon Sep 17 00:00:00 2001 From: Jonas Dellinger Date: Fri, 29 May 2020 13:06:20 +0200 Subject: [PATCH] Added Reflection Cache for RequestParams #451 --- .../Example.CLI.PersistentConfig/Program.cs | 1 + .../Clients/Interfaces/IOAuthClient.cs | 14 ++ .../Models/Request/RequestParams.cs | 130 ++++++++++++------ 3 files changed, 101 insertions(+), 44 deletions(-) diff --git a/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs b/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs index 293e28bf..76861994 100644 --- a/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs +++ b/SpotifyAPI.Web.Examples/Example.CLI.PersistentConfig/Program.cs @@ -62,6 +62,7 @@ namespace Example.CLI.PersistentConfig var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers()); Console.WriteLine($"Total Playlists in your Account: {playlists.Count}"); + _server.Dispose(); Environment.Exit(0); } diff --git a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs index 92816b2f..df1fd4b5 100644 --- a/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs +++ b/SpotifyAPI.Web/Clients/Interfaces/IOAuthClient.cs @@ -4,6 +4,20 @@ namespace SpotifyAPI.Web { public interface IOAuthClient { + /// + /// Requests a new token using client_ids and client_secrets. + /// If the token is expired, simply call the funtion again to get a new token + /// + /// + /// Task RequestToken(ClientCredentialsRequest request); + + /// + /// Refresh an already received token via Authorization Code Auth + /// + /// + /// + Task RequestToken(AuthorizationCodeRefreshRequest request); + Task RequestToken(AuthorizationCodeTokenRequest request); } } diff --git a/SpotifyAPI.Web/Models/Request/RequestParams.cs b/SpotifyAPI.Web/Models/Request/RequestParams.cs index 2762e4e9..6859c2ac 100644 --- a/SpotifyAPI.Web/Models/Request/RequestParams.cs +++ b/SpotifyAPI.Web/Models/Request/RequestParams.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using System.Reflection; using System; using System.Linq; @@ -9,69 +10,73 @@ namespace SpotifyAPI.Web { public abstract class RequestParams { + private static readonly ConcurrentDictionary _bodyParamsCache = + new ConcurrentDictionary(); public JObject BuildBodyParams() { // Make sure everything is okay before building body params CustomEnsure(); - var bodyProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) - .Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0); - - var obj = new JObject(); - foreach (var prop in bodyProps) + var body = new JObject(); + if (!_bodyParamsCache.IsEmpty) { - object value = prop.GetValue(this); - if (value != null && prop.GetCustomAttribute(typeof(BodyParamAttribute)) is BodyParamAttribute attribute) + foreach (var bodyParam in _bodyParamsCache) { - obj[attribute.Key ?? prop.Name] = JToken.FromObject(value); + AddBodyParam(body, bodyParam.Key, bodyParam.Value); } } - return obj; + else + { + var bodyProps = GetType() + .GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) + .Where(prop => prop.GetCustomAttributes(typeof(BodyParamAttribute), true).Length > 0); + + foreach (var prop in bodyProps) + { + var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute)); + _bodyParamsCache[prop] = attribute; + AddBodyParam(body, prop, attribute); + } + } + + return body; } + private void AddBodyParam(JObject body, PropertyInfo prop, BodyParamAttribute attribute) + { + object value = prop.GetValue(this); + if (value != null) + { + body[attribute.Key ?? prop.Name] = JToken.FromObject(value); + } + } + + private static readonly ConcurrentDictionary _queryParamsCache = + new ConcurrentDictionary(); public Dictionary BuildQueryParams() { // Make sure everything is okay before building query params CustomEnsure(); - var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) + var queryParams = new Dictionary(); + + if (!_queryParamsCache.IsEmpty) + { + foreach (var queryParam in _queryParamsCache) + { + AddQueryParam(queryParams, queryParam.Key, queryParam.Value); + } + } + else + { + var queryProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) .Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0); - var queryParams = new Dictionary(); - foreach (var prop in queryProps) - { - object value = prop.GetValue(this); - if (value != null && prop.GetCustomAttribute(typeof(QueryParamAttribute)) is QueryParamAttribute attribute) + foreach (var prop in queryProps) { - if (value is IList list && list.Count > 0) - { - var str = string.Join(",", list); - queryParams.Add(attribute.Key ?? prop.Name, str); - } - else if (value is Enum valueAsEnum) - { - var enumType = valueAsEnum.GetType(); - var valueList = new List(); - - foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType())) - { - if (valueAsEnum.HasFlag(enumVal)) - { - if (enumType - .GetMember(enumVal.ToString())[0] - .GetCustomAttributes(typeof(StringAttribute)) - .FirstOrDefault() is StringAttribute stringAttr) - { - valueList.Add(stringAttr.Value); - } - } - } - queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList)); - } - else - { - queryParams.Add(attribute.Key ?? prop.Name, value.ToString()); - } + var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute)); + _queryParamsCache[prop] = attribute; + AddQueryParam(queryParams, prop, attribute); } } @@ -80,6 +85,43 @@ namespace SpotifyAPI.Web return queryParams; } + private void AddQueryParam(Dictionary queryParams, PropertyInfo prop, QueryParamAttribute attribute) + { + object value = prop.GetValue(this); + if (value != null) + { + if (value is IList list && list.Count > 0) + { + var str = string.Join(",", list); + queryParams.Add(attribute.Key ?? prop.Name, str); + } + else if (value is Enum valueAsEnum) + { + var enumType = valueAsEnum.GetType(); + var valueList = new List(); + + foreach (Enum enumVal in Enum.GetValues(valueAsEnum.GetType())) + { + if (valueAsEnum.HasFlag(enumVal)) + { + if (enumType + .GetMember(enumVal.ToString())[0] + .GetCustomAttributes(typeof(StringAttribute)) + .FirstOrDefault() is StringAttribute stringAttr) + { + valueList.Add(stringAttr.Value); + } + } + } + queryParams.Add(attribute.Key ?? prop.Name, string.Join(",", valueList)); + } + else + { + queryParams.Add(attribute.Key ?? prop.Name, value.ToString()); + } + } + } + protected virtual void CustomEnsure() { } protected virtual void AddCustomQueryParams(Dictionary queryParams) { } }