mirror of
https://github.com/zoriya/octokit.net.git
synced 2026-06-05 11:40:42 +00:00
Make RequestParameters work for RT and perf
Around an 80% perf improvement
This commit is contained in:
@@ -14,74 +14,109 @@ namespace Octokit
|
||||
/// </summary>
|
||||
public abstract class RequestParameters
|
||||
{
|
||||
static readonly ConcurrentDictionary<Type, List<PropertyInfo>> _propertiesMap =
|
||||
new ConcurrentDictionary<Type, List<PropertyInfo>>();
|
||||
static readonly ConcurrentDictionary<Type, List<PropertyParameter>> _propertiesMap =
|
||||
new ConcurrentDictionary<Type, List<PropertyParameter>>();
|
||||
|
||||
public virtual IDictionary<string, string> ToParametersDictionary()
|
||||
{
|
||||
var properties = _propertiesMap.GetOrAdd(GetType(), GetPropertiesForType);
|
||||
|
||||
return (from property in properties
|
||||
let value = GetValue(property)
|
||||
let key = GetKey(property)
|
||||
where value != null
|
||||
select new { key, value }).ToDictionary(kvp => kvp.key, kvp => kvp.value);
|
||||
var map = _propertiesMap.GetOrAdd(GetType(), GetPropertyParametersForType);
|
||||
return (from property in map
|
||||
let value = property.GetValue(this)
|
||||
let key = property.Key
|
||||
where value != null
|
||||
select new { key, value }).ToDictionary(kvp => kvp.key, kvp => kvp.value);
|
||||
}
|
||||
|
||||
static List<PropertyInfo> GetPropertiesForType(Type type)
|
||||
static List<PropertyParameter> GetPropertyParametersForType(Type type)
|
||||
{
|
||||
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
|
||||
return type.GetAllProperties()
|
||||
.Select(p => new PropertyParameter(p))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase",
|
||||
Justification = "GitHub API depends on lower case strings")]
|
||||
static string GetKey(PropertyInfo property)
|
||||
static Func<PropertyInfo, object, string> GetValueFunc(Type propertyType)
|
||||
{
|
||||
var attribute = property.GetCustomAttributes(typeof(ParameterAttribute), false)
|
||||
.Cast<ParameterAttribute>()
|
||||
.FirstOrDefault(attr => attr.Key != null);
|
||||
|
||||
return attribute == null
|
||||
? property.Name.ToLowerInvariant()
|
||||
: attribute.Key;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase",
|
||||
Justification = "GitHub API depends on lower case strings")]
|
||||
string GetValue(PropertyInfo property)
|
||||
{
|
||||
var value = property.GetValue(this, null);
|
||||
|
||||
if (typeof(IEnumerable<string>).IsAssignableFrom(property.PropertyType))
|
||||
if (typeof(IEnumerable<string>).IsAssignableFrom(propertyType))
|
||||
{
|
||||
var list = (IEnumerable<string>)value;
|
||||
return !list.Any() ? null : String.Join(",", list);
|
||||
}
|
||||
|
||||
if (property.PropertyType.IsDateTimeOffset() && value != null)
|
||||
{
|
||||
return ((DateTimeOffset)value).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ",
|
||||
CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (property.PropertyType.IsEnum && value != null)
|
||||
{
|
||||
var member = property.PropertyType.GetMember(value.ToString()).FirstOrDefault();
|
||||
if (member != null)
|
||||
return (prop, value) =>
|
||||
{
|
||||
var attribute = member.GetCustomAttributes(typeof(ParameterAttribute), false)
|
||||
.Cast<ParameterAttribute>()
|
||||
.FirstOrDefault();
|
||||
if (attribute != null)
|
||||
{
|
||||
return attribute.Value;
|
||||
}
|
||||
}
|
||||
var list = ((IEnumerable<string>)value).ToArray();
|
||||
return !list.Any() ? null : String.Join(",", list);
|
||||
};
|
||||
}
|
||||
|
||||
return value != null
|
||||
if (propertyType.IsDateTimeOffset())
|
||||
{
|
||||
return (prop, value) =>
|
||||
{
|
||||
if (value == null) return null;
|
||||
return ((DateTimeOffset)value).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ",
|
||||
CultureInfo.InvariantCulture);
|
||||
};
|
||||
}
|
||||
|
||||
if (propertyType.IsEnumeration())
|
||||
{
|
||||
var enumToAttributeDictionary = Enum.GetNames(propertyType)
|
||||
.ToDictionary(name => name, name => GetParameterAttributeValueForEnumName(propertyType, name));
|
||||
return (prop, value) =>
|
||||
{
|
||||
if (value == null) return null;
|
||||
string attributeValue;
|
||||
|
||||
return enumToAttributeDictionary.TryGetValue(value.ToString(), out attributeValue)
|
||||
? attributeValue ?? value.ToString().ToLowerInvariant()
|
||||
: value.ToString().ToLowerInvariant();
|
||||
};
|
||||
}
|
||||
|
||||
return (prop, value) => value != null
|
||||
? value.ToString().ToLowerInvariant()
|
||||
: null;
|
||||
}
|
||||
|
||||
static string GetParameterAttributeValueForEnumName(Type enumType, string name)
|
||||
{
|
||||
var member = enumType.GetMember(name).FirstOrDefault();
|
||||
if (member == null) return null;
|
||||
var attribute = member.GetCustomAttributes(typeof(ParameterAttribute), false)
|
||||
.Cast<ParameterAttribute>()
|
||||
.FirstOrDefault();
|
||||
return attribute != null ? attribute.Value : null;
|
||||
}
|
||||
|
||||
class PropertyParameter
|
||||
{
|
||||
readonly Func<PropertyInfo, object, string> _valueFunc;
|
||||
readonly PropertyInfo _property;
|
||||
public PropertyParameter(PropertyInfo property)
|
||||
{
|
||||
_property = property;
|
||||
Key = GetParameterKeyFromProperty(property);
|
||||
_valueFunc = GetValueFunc(property.PropertyType);
|
||||
}
|
||||
|
||||
public string Key { get; private set; }
|
||||
|
||||
public string GetValue(object instance)
|
||||
{
|
||||
return _valueFunc(_property, _property.GetValue(instance, null));
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase",
|
||||
Justification = "GitHub API depends on lower case strings")]
|
||||
static string GetParameterKeyFromProperty(PropertyInfo property)
|
||||
{
|
||||
var attribute = property.GetCustomAttributes(typeof(ParameterAttribute), false)
|
||||
.Cast<ParameterAttribute>()
|
||||
.FirstOrDefault(attr => attr.Key != null);
|
||||
|
||||
return attribute == null
|
||||
? property.Name.ToLowerInvariant()
|
||||
: attribute.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user