Example #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);
        }
Example #2
0
        /// <summary>
        /// Convert an IteratorState to an instance of the iterator it represents.
        /// </summary>
        /// <param name="state">An IteratorState instance.</param>
        /// <returns>An equivalent iterator instance.</returns>
        public IEnumerator FromState(IteratorState state)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            Type iteratorType = GetIteratorTypeChecked(state.DeclaringTypeName, state.MethodName);

            IteratorTypeInfo ti = GetIteratorTypeInfo(iteratorType);

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

            var iterator = (IEnumerator)ti.Constructor.Invoke(new object[] { state.State });

            ti.Current.SetValue(iterator, state.Current);
            ti.This?.SetValue(iterator, state.This);

            foreach (KeyValuePair <string, object> a in state.Arguments)
            {
                FieldInfo info;
                if (!ti.Arguments.TryGetValue(a.Key, out info))
                {
                    continue;
                }
                info.SetValue(iterator, a.Value);
            }

            foreach (KeyValuePair <string, object> v in state.Variables)
            {
                FieldInfo info;
                if (!ti.Variables.TryGetValue(v.Key, out info))
                {
                    continue;
                }
                info.SetValue(iterator, v.Value);
            }

            return(iterator);
        }
Example #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);
        }
        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;
        }