diff --git a/Octokit.Tests/Models/RequestParametersTests.cs b/Octokit.Tests/Models/RequestParametersTests.cs
index 516e2369..187e8806 100644
--- a/Octokit.Tests/Models/RequestParametersTests.cs
+++ b/Octokit.Tests/Models/RequestParametersTests.cs
@@ -116,7 +116,7 @@ namespace Octokit.Tests.Models
[Fact]
public void UsesParameterAttributeForKey()
{
- var model = new WithPropertyNameDifferentFromKey() { LongPropertyName = "verbose" };
+ var model = new WithPropertyNameDifferentFromKey() { LongPropertyName = "verbose" };
var result = model.ToParametersDictionary();
diff --git a/Octokit.Tests/OctokitRT.Tests.csproj b/Octokit.Tests/OctokitRT.Tests.csproj
index 17ea6ba9..6112365f 100644
--- a/Octokit.Tests/OctokitRT.Tests.csproj
+++ b/Octokit.Tests/OctokitRT.Tests.csproj
@@ -89,7 +89,7 @@
-
+
diff --git a/Octokit/Helpers/ReflectionExtensions.cs b/Octokit/Helpers/ReflectionExtensions.cs
index d7966b9b..0e35ce7e 100644
--- a/Octokit/Helpers/ReflectionExtensions.cs
+++ b/Octokit/Helpers/ReflectionExtensions.cs
@@ -1,4 +1,8 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
namespace Octokit
{
@@ -11,7 +15,48 @@ namespace Octokit
public static bool IsNullable(this Type type)
{
- return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ return type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
+ }
+
+#if !NETFX_CORE
+ public static Type GetTypeInfo(this Type type)
+ {
+ return type;
+ }
+#endif
+
+#if NETFX_CORE
+ public static IEnumerable GetMember(this Type type, string name)
+ {
+ return type.GetTypeInfo().DeclaredMembers.Where(m => m.Name == name);
+ }
+
+ public static bool IsAssignableFrom(this Type type, Type otherType)
+ {
+ return type.GetTypeInfo().IsAssignableFrom(otherType.GetTypeInfo());
+ }
+#endif
+ public static IEnumerable GetAllProperties(this Type type)
+ {
+#if NETFX_CORE
+ var typeInfo = type.GetTypeInfo();
+ var properties = typeInfo.DeclaredProperties;
+
+ var baseType = typeInfo.BaseType;
+
+ return baseType == null ? properties : properties.Concat(baseType.GetAllProperties());
+#else
+ return type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
+#endif
+ }
+
+ public static bool IsEnumeration(this Type type)
+ {
+#if NETFX_CORE
+ return type.GetTypeInfo().IsEnum;
+#else
+ return type.IsEnum;
+#endif
}
}
}
diff --git a/Octokit/Models/Request/RequestParameters.cs b/Octokit/Models/Request/RequestParameters.cs
index c96d79ee..d47d4312 100644
--- a/Octokit/Models/Request/RequestParameters.cs
+++ b/Octokit/Models/Request/RequestParameters.cs
@@ -14,74 +14,109 @@ namespace Octokit
///
public abstract class RequestParameters
{
- static readonly ConcurrentDictionary> _propertiesMap =
- new ConcurrentDictionary>();
+ static readonly ConcurrentDictionary> _propertiesMap =
+ new ConcurrentDictionary>();
public virtual IDictionary 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 GetPropertiesForType(Type type)
+ static List 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 GetValueFunc(Type propertyType)
{
- var attribute = property.GetCustomAttributes(typeof(ParameterAttribute), false)
- .Cast()
- .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).IsAssignableFrom(property.PropertyType))
+ if (typeof(IEnumerable).IsAssignableFrom(propertyType))
{
- var list = (IEnumerable)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()
- .FirstOrDefault();
- if (attribute != null)
- {
- return attribute.Value;
- }
- }
+ var list = ((IEnumerable)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()
+ .FirstOrDefault();
+ return attribute != null ? attribute.Value : null;
+ }
+
+ class PropertyParameter
+ {
+ readonly Func _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()
+ .FirstOrDefault(attr => attr.Key != null);
+
+ return attribute == null
+ ? property.Name.ToLowerInvariant()
+ : attribute.Key;
+ }
+ }
}
}
diff --git a/Octokit/OctokitRT.csproj b/Octokit/OctokitRT.csproj
index 1ba1753c..45e0b9f6 100644
--- a/Octokit/OctokitRT.csproj
+++ b/Octokit/OctokitRT.csproj
@@ -149,6 +149,7 @@
+
@@ -192,6 +193,7 @@
+