Merge branch 'Reflection' of Common/Utils into dev

This commit is contained in:
Jeffery Thompson
2018-04-05 15:37:29 +00:00
committed by Gogs
4 changed files with 136 additions and 1 deletions

View File

@@ -10,6 +10,14 @@ namespace ICD.Common.Utils.Tests.Extensions
[TestFixture]
public sealed class TypeExtensionsTest
{
[TestCase(typeof(byte), false)]
[TestCase(typeof(byte?), true)]
[TestCase(typeof(string), true)]
public void CanBeNullTest(Type value, bool expected)
{
Assert.AreEqual(expected, value.CanBeNull());
}
[TestCase(typeof(byte), true)]
[TestCase(typeof(decimal), true)]
[TestCase(typeof(double), true)]
@@ -61,6 +69,23 @@ namespace ICD.Common.Utils.Tests.Extensions
Assert.AreEqual(expected, value.IsDecimalNumeric());
}
[TestCase(typeof(byte), true)]
[TestCase(typeof(decimal), false)]
[TestCase(typeof(double), false)]
[TestCase(typeof(float), false)]
[TestCase(typeof(int), true)]
[TestCase(typeof(long), true)]
[TestCase(typeof(sbyte), true)]
[TestCase(typeof(short), true)]
[TestCase(typeof(uint), true)]
[TestCase(typeof(ulong), true)]
[TestCase(typeof(ushort), true)]
[TestCase(typeof(string), false)]
public void IsIntegerNumericTest(Type value, bool expected)
{
Assert.AreEqual(expected, value.IsIntegerNumeric());
}
[TestCase(typeof(string), typeof(object), true)]
[TestCase(typeof(object), typeof(string), false)]
public void IsAssignableToTest(Type a, Type b, bool expected)

View File

@@ -121,9 +121,33 @@ namespace ICD.Common.Utils.Tests
}
[Test]
public void LoadAssemblyFromPath()
public void LoadAssemblyFromPathTest()
{
Assert.Inconclusive();
}
[Test]
public void GetImplementationTest()
{
Assert.Inconclusive();
}
[Test]
public void ChangeTypeTest()
{
// Same type
Assert.AreEqual(10, ReflectionUtils.ChangeType(10, typeof(int)));
// Null
Assert.AreEqual(null, ReflectionUtils.ChangeType(null, typeof(string)));
// Enums
Assert.AreEqual(BindingFlags.GetProperty, ReflectionUtils.ChangeType((int)(object)BindingFlags.GetProperty, typeof(BindingFlags)));
Assert.AreEqual(BindingFlags.GetProperty, ReflectionUtils.ChangeType(BindingFlags.GetProperty.ToString(), typeof(BindingFlags)));
Assert.AreEqual(BindingFlags.GetProperty, ReflectionUtils.ChangeType(((int)(object)BindingFlags.GetProperty).ToString(), typeof(BindingFlags)));
// Everything else
Assert.AreEqual(10, ReflectionUtils.ChangeType("10", typeof(int)));
}
}
}

View File

@@ -45,6 +45,18 @@ namespace ICD.Common.Utils.Extensions
typeof(float),
};
private static readonly IcdHashSet<Type> s_IntegerNumericTypes = new IcdHashSet<Type>
{
typeof(byte),
typeof(int),
typeof(long),
typeof(sbyte),
typeof(short),
typeof(uint),
typeof(ulong),
typeof(ushort)
};
private static readonly Dictionary<Type, Type[]> s_TypeAllTypes;
private static readonly Dictionary<Type, Type[]> s_TypeBaseTypes;
private static readonly Dictionary<Type, Type[]> s_TypeImmediateInterfaces;
@@ -61,6 +73,19 @@ namespace ICD.Common.Utils.Extensions
s_TypeMinimalInterfaces = new Dictionary<Type, Type[]>();
}
/// <summary>
/// Returns true if the given type can represent a null value.
/// </summary>
/// <param name="extends"></param>
/// <returns></returns>
public static bool CanBeNull(this Type extends)
{
if (extends == null)
throw new ArgumentException("extends");
return !extends.IsValueType || Nullable.GetUnderlyingType(extends) != null;
}
/// <summary>
/// Returns true if the given type is a numeric type.
/// </summary>
@@ -100,6 +125,24 @@ namespace ICD.Common.Utils.Extensions
return s_DecimalNumericTypes.Contains(extends);
}
/// <summary>
/// Returns true if the given type is an integer numeric type.
/// </summary>
/// <param name="extends"></param>
/// <returns></returns>
public static bool IsIntegerNumeric(this Type extends)
{
if (extends == null)
throw new ArgumentException("extends");
return s_IntegerNumericTypes.Contains(extends);
}
/// <summary>
/// Gets the Assembly containing the type.
/// </summary>
/// <param name="extends"></param>
/// <returns></returns>
public static Assembly GetAssembly(this Type extends)
{
if (extends == null)
@@ -114,6 +157,12 @@ namespace ICD.Common.Utils.Extensions
.Assembly;
}
/// <summary>
/// Returns true if the type is assignable to the given type.
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <returns></returns>
public static bool IsAssignableTo(this Type from, Type to)
{
if (from == null)

View File

@@ -368,5 +368,42 @@ namespace ICD.Common.Utils
? property
: GetImplementation(property.DeclaringType, property);
}
/// <summary>
/// Changes the given value to the given type.
/// </summary>
/// <param name="value"></param>
/// <param name="type"></param>
/// <returns></returns>
public static object ChangeType(object value, Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// Handle null value
if (value == null)
{
if (type.CanBeNull())
return null;
throw new InvalidCastException();
}
Type valueType = value.GetType();
if (valueType.IsAssignableTo(type))
return value;
// Handle enum
if (type.IsEnum)
{
if (valueType.IsIntegerNumeric())
return Enum.ToObject(type, value);
if (value is string)
return Enum.Parse(type, value as string, false);
}
return Convert.ChangeType(value, type, null);
}
}
}