using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace UnityEngine.Localization.SmartFormat.Utilities { /// /// Extensions for s. /// /// /// Credits to James Esh for the code posted on /// https://stackoverflow.com/questions/46707556/detect-if-an-object-is-a-valuetuple /// public static class TupleExtensions { // value tuples can have a maximum of 7 elements private static readonly HashSet ValueTupleTypes = new HashSet(new Type[] { typeof(ValueTuple<>), typeof(ValueTuple<,>), typeof(ValueTuple<, ,>), typeof(ValueTuple<, , ,>), typeof(ValueTuple<, , , ,>), typeof(ValueTuple<, , , , ,>), typeof(ValueTuple<, , , , , ,>), typeof(ValueTuple<, , , , , , ,>) }); /// /// Extension method to check whether an object is of type /// /// /// Returns true, if the object is of type . public static bool IsValueTuple(this object obj) => IsValueTupleType(obj.GetType()); /// /// Extension method to check whether the given type is a /// /// /// Returns true, if the type is a . public static bool IsValueTupleType(this Type type) { return type.GetTypeInfo().IsGenericType && ValueTupleTypes.Contains(type.GetGenericTypeDefinition()); } /// /// A list of s with the values for each field. /// /// /// Returns a list of s with the values for each field. public static IEnumerable GetValueTupleItemObjects(this object tuple) => GetValueTupleItemFields(tuple.GetType()).Select(f => f.GetValue(tuple)); /// /// A list of s for the fields of a . /// /// /// Returns of list of s with the fields of a . public static IEnumerable GetValueTupleItemTypes(this Type tupleType) => GetValueTupleItemFields(tupleType).Select(f => f.FieldType); /// /// A list of s with the fields of a . /// /// /// Returns of list of s with the fields of a . public static List GetValueTupleItemFields(this Type tupleType) { var items = new List(); FieldInfo field; var nth = 1; while ((field = tupleType.GetRuntimeField($"Item{nth}")) != null) { nth++; items.Add(field); } return items; } public static IEnumerable GetValueTupleItemObjectsFlattened(this object tuple) { foreach (var theTuple in tuple.GetValueTupleItemObjects()) { if (theTuple.IsValueTuple()) { foreach (var innerTuple in theTuple.GetValueTupleItemObjectsFlattened()) { yield return innerTuple; } } else { yield return theTuple; } } } } }