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); }
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); }
/// <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); }