using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using RestEase.Platform;
namespace RestEase.Implementation
{
///
/// Helper to iterate both IDictionary and IDictionary{TKey, TValue} instances, as if both were IEnumerable{KeyValuePair{object, object}}
///
public static class DictionaryIterator
{
#if NETSTANDARD
private static readonly MethodInfo iterateGenericTypedMethod = typeof(DictionaryIterator).GetTypeInfo().GetDeclaredMethod("IterateGenericTyped");
#else
private static readonly MethodInfo iterateGenericTypedMethod = typeof(DictionaryIterator).GetMethod("IterateGenericTyped", BindingFlags.NonPublic | BindingFlags.Static);
#endif
///
/// Returns true if we're capable of iterating the supplied type
///
/// Type to check
/// True if we're capable of iterating it
public static bool CanIterate(Type dictionaryType)
{
var dictionaryTypeInfo = dictionaryType.GetTypeInfo();
return typeof(IDictionary).GetTypeInfo().IsAssignableFrom(dictionaryTypeInfo) ||
(dictionaryTypeInfo.IsGenericType && dictionaryType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) ||
dictionaryTypeInfo.GetInterfaces().Any(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary<,>));
}
///
/// Iterates the given IDictionary or IDictionary{TKey, TValue} as if it was an IEnumerable{KeyValuePair{object, object}}
///
/// Dictionary to iterate
/// The equivalent IEnumerable{KeyValuePair{object, object}}
public static IEnumerable> Iterate(object dictionary)
{
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
if (dictionary is IDictionary nonGeneric)
return IterateNonGeneric(nonGeneric);
// 'dictionary' cannot be an interface, so we're safe skipping to see whether
// dictionary.GetType().GetGenericTypeDefinition() == IDictionary<,>
foreach (var interfaceType in dictionary.GetType().GetTypeInfo().GetInterfaces())
{
var interfaceTypeInfo = interfaceType.GetTypeInfo();
if (interfaceTypeInfo.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>))
return IterateGeneric(dictionary, interfaceType);
}
throw new ArgumentException("Dictionary does not implement IDictionary or IDictionary", nameof(dictionary));
}
private static IEnumerable> IterateNonGeneric(IDictionary dictionary)
{
foreach (DictionaryEntry entry in dictionary)
{
yield return new KeyValuePair