Added Reflection Cache for RequestParams #451

This commit is contained in:
Jonas Dellinger 2020-05-29 13:06:20 +02:00
parent f105fcbd0e
commit 0ef07bed0b
3 changed files with 101 additions and 44 deletions

View File

@ -62,6 +62,7 @@ namespace Example.CLI.PersistentConfig
var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers()); var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers());
Console.WriteLine($"Total Playlists in your Account: {playlists.Count}"); Console.WriteLine($"Total Playlists in your Account: {playlists.Count}");
_server.Dispose();
Environment.Exit(0); Environment.Exit(0);
} }

View File

@ -4,6 +4,20 @@ namespace SpotifyAPI.Web
{ {
public interface IOAuthClient public interface IOAuthClient
{ {
/// <summary>
/// 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
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<CredentialsTokenResponse> RequestToken(ClientCredentialsRequest request); Task<CredentialsTokenResponse> RequestToken(ClientCredentialsRequest request);
/// <summary>
/// Refresh an already received token via Authorization Code Auth
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<AuthorizationCodeRefreshResponse> RequestToken(AuthorizationCodeRefreshRequest request);
Task<AuthorizationCodeTokenResponse> RequestToken(AuthorizationCodeTokenRequest request);
} }
} }

View File

@ -1,3 +1,4 @@
using System.Collections.Concurrent;
using System.Reflection; using System.Reflection;
using System; using System;
using System.Linq; using System.Linq;
@ -9,39 +10,85 @@ namespace SpotifyAPI.Web
{ {
public abstract class RequestParams public abstract class RequestParams
{ {
private static readonly ConcurrentDictionary<PropertyInfo, BodyParamAttribute> _bodyParamsCache =
new ConcurrentDictionary<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 bodyProps = GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public) var body = new JObject();
if (!_bodyParamsCache.IsEmpty)
{
foreach (var bodyParam in _bodyParamsCache)
{
AddBodyParam(body, bodyParam.Key, bodyParam.Value);
}
}
else
{
var bodyProps = GetType()
.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);
var obj = new JObject();
foreach (var prop in bodyProps) foreach (var prop in bodyProps)
{ {
object value = prop.GetValue(this); var attribute = (BodyParamAttribute)prop.GetCustomAttribute(typeof(BodyParamAttribute));
if (value != null && prop.GetCustomAttribute(typeof(BodyParamAttribute)) is BodyParamAttribute attribute) _bodyParamsCache[prop] = attribute;
{ AddBodyParam(body, prop, attribute);
obj[attribute.Key ?? prop.Name] = JToken.FromObject(value);
} }
} }
return obj;
}
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<PropertyInfo, QueryParamAttribute> _queryParamsCache =
new ConcurrentDictionary<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>();
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) 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);
var queryParams = new Dictionary<string, string>();
foreach (var prop in queryProps) foreach (var prop in queryProps)
{
var attribute = (QueryParamAttribute)prop.GetCustomAttribute(typeof(QueryParamAttribute));
_queryParamsCache[prop] = attribute;
AddQueryParam(queryParams, prop, attribute);
}
}
AddCustomQueryParams(queryParams);
return queryParams;
}
private void AddQueryParam(Dictionary<string, string> queryParams, PropertyInfo prop, QueryParamAttribute attribute)
{ {
object value = prop.GetValue(this); object value = prop.GetValue(this);
if (value != null && prop.GetCustomAttribute(typeof(QueryParamAttribute)) is QueryParamAttribute attribute) if (value != null)
{ {
if (value is IList<string> list && list.Count > 0) if (value is IList<string> list && list.Count > 0)
{ {
@ -75,11 +122,6 @@ namespace SpotifyAPI.Web
} }
} }
AddCustomQueryParams(queryParams);
return queryParams;
}
protected virtual void CustomEnsure() { } protected virtual void CustomEnsure() { }
protected virtual void AddCustomQueryParams(Dictionary<string, string> queryParams) { } protected virtual void AddCustomQueryParams(Dictionary<string, string> queryParams) { }
} }