Skip to content

Instantly share code, notes, and snippets.

@jwcarroll
Created April 6, 2011 20:29
Show Gist options
  • Save jwcarroll/906456 to your computer and use it in GitHub Desktop.
Save jwcarroll/906456 to your computer and use it in GitHub Desktop.
Will map a string value to pretty much any primitive type. It also handles lists of values.
public static class ReflectionExtensions
{
public static Boolean Implements<T>(this Type typeToCheck)
{
return typeToCheck.Implements(typeof(T));
}
public static Boolean Implements(this Type typeToCheck, Type typeToCheckFor)
{
if (typeToCheck == null || typeToCheckFor == null) return false;
if (typeToCheck == typeToCheckFor) return true;
if (typeToCheckFor.IsInterface)
return typeToCheck.ImplementsInterface(typeToCheckFor);
else
return typeToCheckFor.IsAssignableFrom(typeToCheck);
}
private static Boolean ImplementsInterface<TInterface>(this Type typeToCheck)
{
return typeToCheck.ImplementsInterface(typeof(TInterface));
}
private static Boolean ImplementsInterface(this Type typeToCheck, Type typeToCheckFor)
{
if (typeToCheck == null || typeToCheckFor == null) return false;
var implementsInterface = false;
if (typeToCheckFor.IsGenericType)
{
implementsInterface = typeToCheck.GetInterfaces().Any(x =>
x.IsGenericType &&
x.GetGenericTypeDefinition() == typeToCheckFor);
}
else
{
implementsInterface = typeToCheckFor.IsAssignableFrom(typeToCheck);
}
return implementsInterface;
}
}
/// <summary>
/// Tries to convert a string value into the type specified. Handles
/// most primitive types, as well as the ability to convert comma
/// delimited values into collections, so long as the individual values
/// are one of the supported types.
/// </summary>
/// <example>
/// Int32 myInt = 0;
/// TryConvertValue("1", typeof(Int32), out myInt);
///
/// List<Int32> myIntList = null;
/// TryConvertValue("1,2,3,4,5", typeof(List<Int32>), out myIntList);
/// </example>
/// <param name="rawValue">The raw string value to be converted.</param>
/// <param name="type">The type that you want to convert the string to.</param>
/// <param name="value">The final converted value.</param>
/// <returns>True if the conversion is successful</returns>
private Boolean TryConvertValue(String rawValue, Type type, out Object value)
{
value = null;
var success = false;
try
{
if (type.IsEnum)
value = Enum.Parse(type, rawValue, true);
else if (type == typeof(Guid))
value = Guid.Parse(rawValue);
else if (type.IsArray)
value = CreateArray(type, rawValue);
else if (type.Implements<IList>())
value = CreateCollection(type, rawValue);
else if (type.Implements(typeof(ICollection<>)))
value = CreateCollection(type, rawValue);
else
value = Convert.ChangeType(rawValue, type);
success = true;
}
catch (Exception ex)
{
Log.Exception(EventID.SettingsServiceConversionFailed, ex);
}
return success;
}
private object CreateArray(Type type, string rawValue)
{
Type listElementTypeParam = type.GetElementType();
var values = rawValue.Split(',');
var array = Array.CreateInstance(listElementTypeParam, values.Length);
for (int i = 0; i < array.Length; i++ )
{
Object val = null;
if (TryConvertValue(values[i], listElementTypeParam, out val))
array.SetValue(val, i);
}
return array;
}
private object CreateCollection(Type type, string rawValue)
{
Type collectionElementTypeParam = null;
if (type.IsGenericType)
collectionElementTypeParam = type.GetGenericArguments()[0];
dynamic collection = Activator.CreateInstance(type);
foreach (var value in rawValue.Split(','))
{
dynamic objVal = null;
if (collectionElementTypeParam != null && TryConvertValue(value, collectionElementTypeParam, out objVal))
collection.Add(objVal);
else
collection.Add(value);
}
return collection;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment