/// <summary> /// Checks whether the specified type is a packed tuple. /// </summary> /// <param name="type">Type to check.</param> /// <returns>true if the specified type is a tuple; otherwise, false.</returns> public static bool IsTuple(Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (!type.IsGenericType() || type.IsGenericTypeDefinition()) { return(false); } var genDef = type.GetGenericTypeDefinition(); if (!TupleTypes.Contains(genDef)) { return(false); } if (genDef == TupleTypes[TupleTypeCount - 1]) { return(IsTuple(type.GetGenericArguments().Last())); } return(true); }
private bool IsTupleAccessor(MemberExpression node, out int position) { var decl = node.Member.DeclaringType; if (decl.IsGenericType() && TupleTypes.Contains(decl.GetGenericTypeDefinition())) { var n = 0; #if USE_SLIM var name = ((PropertyInfoSlim)node.Member).Name; #else var name = node.Member.Name; #endif if (name == "Rest") { n = TupleTypeCount - 2; } else { n = name[4 /* "Item".Length */] - '0'; } if (node.Expression is MemberExpression lhs && IsTupleAccessor(lhs, out position)) { position += n; return(true); } if (ReferenceEquals(node.Expression, _tupleParameter)) { position = n; return(true); } } position = 0; return(false); }
private static IEnumerable <Expression> UnpackImplIterator(Expression expression) { var maxTupleType = TupleTypes[TupleTypeCount - 1]; var tuple = expression; while (tuple != null) { if (tuple is not NewExpression newExpr) { throw new InvalidOperationException("Only NewExpression nodes can be used to unpack tuples."); } var type = newExpr.Type; var tupleType = default(Type); if (type.IsGenericType()) { tupleType = type.GetGenericTypeDefinition(); } if (tupleType == null || !TupleTypes.Contains(tupleType)) { throw new InvalidOperationException("Specified type is not a tuple type."); } var hasRest = tupleType == maxTupleType; #if USE_SLIM var n = newExpr.ArgumentCount - (hasRest ? 1 : 0); for (var i = 0; i < n; i++) { var arg = newExpr.GetArgument(i); yield return(arg); } if (hasRest) { tuple = newExpr.GetArgument(n); } #else var n = newExpr.Arguments.Count - (hasRest ? 1 : 0); for (var i = 0; i < n; i++) { var arg = newExpr.Arguments[i]; yield return(arg); } if (hasRest) { tuple = newExpr.Arguments[n]; } #endif else { tuple = null; } } }