Last active
August 29, 2015 14:21
-
-
Save hediet/3256b1f113d0b4a6c2a0 to your computer and use it in GitHub Desktop.
ListConverter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
namespace Hediet.Common | |
{ | |
/// <summary> | |
/// Casts a list of objects to a strong typed list of any type. | |
/// </summary> | |
public static class ListConverter | |
{ | |
/// <summary> | |
/// Creates a list of type <paramref name="expectedListType"/> with items from <paramref name="items"/>. | |
/// </summary> | |
/// <param name="expectedListType">The type of the returned list. Cannot be null.</param> | |
/// <param name="items">The source list. Cannot be null.</param> | |
/// <returns>The list of type <paramref name="expectedListType"/>. Will not be null.</returns> | |
public static object CreateListOfType(Type expectedListType, IEnumerable items) | |
{ | |
if (expectedListType == null) throw new ArgumentNullException("expectedListType"); | |
if (items == null) throw new ArgumentNullException("items"); | |
return CreateListOfType(expectedListType, t => items); | |
} | |
/// <summary> | |
/// Creates a list of type <paramref name="expectedListType"/>. | |
/// The items are obtained by calling <paramref name="itemsFunc"/> with the item type of the list to create. | |
/// Valid list types are all types which are assignable from List<T< and T[] where T can be any type. | |
/// </summary> | |
/// <param name="expectedListType">The type of the returned list. Cannot be null.</param> | |
/// <param name="itemsFunc">The source list function. Cannot be null.</param> | |
/// <returns>The list of type <paramref name="expectedListType"/>. Will not be null.</returns> | |
public static object CreateListOfType(Type expectedListType, Func<Type, IEnumerable> itemsFunc) | |
{ | |
if (expectedListType == null) throw new ArgumentNullException("expectedListType"); | |
if (itemsFunc == null) throw new ArgumentNullException("itemsFunc"); | |
if (expectedListType.IsArray) | |
{ | |
var elementType = expectedListType.GetElementType(); | |
return CreateItems(itemsFunc(elementType), elementType, "Array"); | |
} | |
if (expectedListType.IsGenericType) | |
{ | |
var genericTypeDefinition = expectedListType.GetGenericTypeDefinition(); | |
var elementType = expectedListType.GetGenericArguments()[0]; | |
if (genericTypeDefinition == typeof(IEnumerable<>)) | |
{ | |
return CreateItems(itemsFunc(elementType), elementType, "Enumerable"); | |
} | |
else if (expectedListType.IsAssignableFrom(typeof(List<>).MakeGenericType(elementType))) | |
{ | |
return CreateItems(itemsFunc(elementType), elementType, "List"); | |
} | |
} | |
throw new ArgumentException(string.Format("{0} is not supported.", expectedListType), "expectedListType"); | |
} | |
/// <summary> | |
/// Checkes whether <paramref name="listType"/> is a valid list type. | |
/// Valid list types are all types which are assignable from List<T< and T[] where T can be any type. | |
/// </summary> | |
/// <param name="listType">The type to check.</param> | |
/// <returns>True, if listType is a valid list type, otherwise false.</returns> | |
public static bool IsSupportedListType(Type listType) | |
{ | |
if (listType == null) throw new ArgumentNullException("listType"); | |
if (listType.IsArray) | |
{ | |
return true; | |
} | |
if (listType.IsGenericType) | |
{ | |
var genericTypeDefinition = listType.GetGenericTypeDefinition(); | |
var elementType = listType.GetGenericArguments()[0]; | |
if (genericTypeDefinition == typeof(IEnumerable<>)) | |
{ | |
return true; | |
} | |
else if (listType.IsAssignableFrom(typeof(List<>).MakeGenericType(elementType))) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
private static IEnumerable CreateItems(IEnumerable items, Type itemType, string targetType) | |
{ | |
var method = typeof(ListConverter).GetMethod("CreateGenericItems" + targetType, | |
BindingFlags.Static | BindingFlags.NonPublic); | |
var result = method.MakeGenericMethod(itemType).Invoke(null, new object[] { items }); | |
return (IEnumerable)result; | |
} | |
// This methods are used for reflection only | |
// ReSharper disable UnusedMember.Local | |
private static IEnumerable<T> CreateGenericItemsEnumerable<T>(IEnumerable itemImplementations) | |
{ | |
return itemImplementations.Cast<T>(); | |
} | |
private static IEnumerable<T> CreateGenericItemsList<T>(IEnumerable itemImplementations) | |
{ | |
return itemImplementations.Cast<T>().ToList(); | |
} | |
private static IEnumerable<T> CreateGenericItemsArray<T>(IEnumerable itemImplementations) | |
{ | |
return itemImplementations.Cast<T>().ToArray(); | |
} | |
// ReSharper restore UnusedMember.Local | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment