Skip to content

Instantly share code, notes, and snippets.

@hediet
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hediet/3256b1f113d0b4a6c2a0 to your computer and use it in GitHub Desktop.
Save hediet/3256b1f113d0b4a6c2a0 to your computer and use it in GitHub Desktop.
ListConverter
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&lt;T&lt; 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&lt;T&lt; 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