Пример #1
0
        private IteratorTypeInfo CreateIteratorTypeInfo(Type type)
        {
            TypeInfo typeInfo = type.GetTypeInfo();

            var fi = new IteratorTypeInfo
            {
                Type        = type,
                MethodName  = NameUtility.ParseOriginalName(type.Name),
                Constructor = typeInfo.DeclaredConstructors.FirstOrDefault(c => !c.IsStatic)
            };

            foreach (FieldInfo field in typeInfo.DeclaredFields)
            {
                char   typeChar;
                string suffix;
                string original;
                if (NameUtility.TryParseGeneratedName(field.Name, out typeChar, out suffix, out original))
                {
                    if (typeChar == StateTypeChar)
                    {
                        // Must check suffix too since <>1__managedThreadId is also used
                        if (suffix == StateSuffix)
                        {
                            fi.State = field;
                        }
                    }
                    else if (typeChar == CurrentTypeChar)
                    {
                        fi.Current = field;
                    }
                    else if (typeChar == ThisTypeChar)
                    {
                        fi.This = field;
                    }
                    else if (typeChar == ArgumentTypeChar)
                    {
                        fi.Arguments.Add(original ?? suffix, field);
                    }
                    else if (typeChar == HoistedVariableTypeChar)
                    {
                        Debug.Assert(original != null);
                        fi.Variables.Add(original, field);
                    }
                }
                else
                {
                    Debug.Assert(!field.IsPublic);
                    fi.Variables.Add(field.Name, field);
                }
            }

            if (fi.Current == null || fi.State == null || fi.Constructor == null)
            {
                return(null);
            }

            return(fi);
        }
Пример #2
0
        private Type GetIteratorTypeChecked(string declaringTypeName, string methodName)
        {
            Type declaringType = Type.GetType(declaringTypeName, true);

            Tuple <string, string> key = Tuple.Create(declaringType.AssemblyQualifiedName, methodName);

            Type iteratorType;

            if (_iteratorTypes.TryGetValue(key, out iteratorType))
            {
                return(iteratorType);
            }

            TypeInfo declaringTypeInfo = declaringType.GetTypeInfo();

            MethodInfo method = declaringTypeInfo.GetDeclaredMethod(methodName);

            if (method == null || !(s_enumeratorType.IsAssignableFrom(method.ReturnType.GetTypeInfo()) || s_enumerableType.IsAssignableFrom(method.ReturnType.GetTypeInfo())))
            {
                throw new ArgumentException("invalid iterator method name: " + methodName, nameof(methodName));
            }

            foreach (TypeInfo nt in declaringTypeInfo.DeclaredNestedTypes)
            {
                char   typeChar;
                string suffix;
                string original;
                if (NameUtility.TryParseGeneratedName(nt.Name, out typeChar, out suffix, out original) && typeChar == StateMachineTypeChar && original == methodName)
                {
                    iteratorType = nt.AsType();
                    break;
                }
            }

            if (iteratorType == null)
            {
                throw new ArgumentException($"no iterator state machine type found for method {methodName} and type {declaringType.AssemblyQualifiedName}");
            }

            _iteratorTypes.Add(key, iteratorType);

            return(iteratorType);
        }
Пример #3
0
        /// <summary>
        /// Convert an iterator to an IteratorState.
        /// </summary>
        /// <param name="iterator">The iterator instance.</param>
        /// <returns>An equivalent IteratorState instance that can be serialized.</returns>
        /// <exception cref="ArgumentNullException">iterator is null</exception>
        /// <exception cref="ArgumentOutOfRangeException">iterator is not a compiler-generated iterator state machine.</exception>
        public IteratorState ToState(IEnumerator iterator)
        {
            if (iterator == null)
            {
                throw new ArgumentNullException(nameof(iterator));
            }

            IteratorTypeInfo ti = GetIteratorTypeInfo(iterator.GetType());

            if (ti == null)
            {
                throw new ArgumentOutOfRangeException(nameof(iterator), "not an iterator state machine type");
            }

            var state = new IteratorState
            {
                DeclaringTypeName = NameUtility.GetSimpleAssemblyQualifiedName(ti.Type.DeclaringType),
                MethodName        = ti.MethodName,
                State             = (int)ti.State.GetValue(iterator),
                Current           = ti.Current.GetValue(iterator)
            };

            if (ti.This != null)
            {
                state.This = ti.This.GetValue(iterator);
            }

            foreach (KeyValuePair <string, FieldInfo> a in ti.Arguments)
            {
                state.Arguments.Add(a.Key, a.Value.GetValue(iterator));
            }

            foreach (KeyValuePair <string, FieldInfo> v in ti.Variables)
            {
                state.Variables.Add(v.Key, v.Value.GetValue(iterator));
            }

            return(state);
        }