예제 #1
0
        /// <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);
        }
예제 #2
0
            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);
            }
예제 #3
0
        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;
                }
            }
        }