Last active
October 16, 2024 19:48
-
-
Save cajuncoding/c02c5161da146f047df579273cdb4df6 to your computer and use it in GitHub Desktop.
Extensions for non-generic Cast(), ToArray() & ToList() that work with Type variables (vs Generic Type parameters)
This file contains 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.Collections.Specialized; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Fasterflect; | |
namespace CajunCoding | |
{ | |
public static class TypeCache | |
{ | |
public static readonly Type StringType = typeof(string); | |
public static readonly Type EnumerableType = typeof(Enumerable); | |
} | |
/// <summary> | |
/// A set of non-generic extensions for IEnumerable to support Cast(), ToArray(), and ToList() conversions using Type variables | |
/// instead of Generic type parameters. This uses the really great Fasterflect library under the hood to ensure very high performance for the | |
/// reflection operations. | |
/// | |
/// Even though Fasterflect is a dependency, if you are using with reflection operations such as this then you should certainly be using Fasterflect | |
/// as it can dramatically improve performance while greatly simplifying your code at the same time! | |
/// </summary> | |
public static class IEnumerableListConversionExtensions | |
{ | |
/// <summary> | |
/// Cast the enumerable (non-generic and/or unknown type) to an IEnumerable using Cast<T> for the Type variable specified. | |
/// This is different from the generic invocation of ToArray<T> because it allows dynamic conversion when the type is not known at compile time. | |
/// The result of this can be cast to a known T[] without casting errors which would occur if you had object[]; | |
/// </summary> | |
/// <param name="source"></param> | |
/// <param name="outputType"></param> | |
/// <returns></returns> | |
public static IEnumerable Cast(this IEnumerable source, Type outputType) | |
//NOTE: Cast<TResult>() is an extension method that is actually defined on the Enumerable static class which is how we need to reference it... | |
=> (IEnumerable)TypeCache.EnumerableType.CallMethod(genericTypes: [outputType], name: nameof(Enumerable.Cast), source); | |
/// <summary> | |
/// Convert the enumerable (non-generic and/or unknown type) to a list using ToArray() for the Type variable specified. | |
/// This is different from the generic invocation of ToArray<T> because it allows dynamic conversion when the type is not known at compile time. | |
/// The result of this can be cast to a known T[] without casting errors which would occur if you had object[]; | |
/// </summary> | |
/// <param name="source"></param> | |
/// <param name="outputType"></param> | |
/// <returns></returns> | |
public static Array ToArray(this IEnumerable source, Type outputType) | |
=> source is not null | |
//NOTE: ToArray<TSource>() is an extension method that is actually defined on the Enumerable static class which is how we need to reference it... | |
? (Array)TypeCache.EnumerableType.CallMethod(genericTypes: [outputType], name: nameof(Enumerable.ToArray), source.Cast(outputType)) | |
: null; | |
/// <summary> | |
/// Convert the enumerable (non-generic and/or unknown type) to a list using ToList() for the Type variable specified. | |
/// This is different from the generic invocation of ToList<T> because it allows dynamic conversion when the type is not known at compile time. | |
/// The result of this can be cast to a known List<T> without casting errors which would occur if you had <object> | |
/// </summary> | |
/// <param name="source"></param> | |
/// <param name="outputType"></param> | |
/// <returns></returns> | |
public static IList ToList(this IEnumerable source, Type outputType) | |
=> source is not null | |
//NOTE: ToArray<TSource>() is an extension method that is actually defined on the Enumerable static class which is how we need to reference it... | |
? (IList)TypeCache.EnumerableType.CallMethod(genericTypes: [outputType], name: nameof(Enumerable.ToList), source.Cast(outputType)) | |
: null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage of this is now very very simple....