public AsyncStateMachineMetadata( Type stateMachineType, AsyncStateMachineField owner, AsyncStateMachineField state, AsyncStateMachineField builder, AsyncStateMachineField[] inputArgs, AsyncStateMachineField[] localVars) { StateMachineType = stateMachineType; Owner = owner; State = state; Builder = builder; InputArguments = inputArgs; LocalVariables = localVars; }
public AsyncStateMachineMetadata Build(Type stateMachineType) { if (stateMachineType == null) { throw new ArgumentNullException(nameof(stateMachineType)); } var fields = stateMachineType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); var inputArguments = new List <AsyncStateMachineField>(); var localVariables = new List <AsyncStateMachineField>(); AsyncStateMachineField?owner = null; AsyncStateMachineField?state = null; AsyncStateMachineField?builder = null; Type builderType = null; var isCompilerGeneratedAsm = stateMachineType #if NETSTANDARD .GetTypeInfo() #endif .GetCustomAttribute <CompilerGeneratedAttribute>() != null; foreach (var fi in fields) { bool isCompilerGeneratedField = false; string name = fi.Name; string internalName = name; if (name[0] == '<') { isCompilerGeneratedField = true; var closingBracketIndex = fi.Name.IndexOf('>'); name = fi.Name.Substring(1, closingBracketIndex - 1); internalName = fi.Name.Substring(closingBracketIndex + 1); } if ((isCompilerGeneratedField && name.Length == 0 && fi.Name.EndsWith("__this")) || (!isCompilerGeneratedField && fi.Name == "__this")) { if (isCompilerGeneratedField) { name = "__this"; } owner = new AsyncStateMachineField(AsyncStateMachineFieldType.OwnerReference, fi, name, internalName); } else if (fi.FieldType == typeof(int) && ( (isCompilerGeneratedField && name.Length == 0 && fi.Name.EndsWith("__state")) || (!isCompilerGeneratedField && fi.Name == "__state"))) { if (isCompilerGeneratedField) { name = "__state"; } state = new AsyncStateMachineField(AsyncStateMachineFieldType.State, fi, name, internalName); } else if (/*name.Length == 0 && fi.Name.EndsWith("__builder") &&*/ (fi.FieldType == typeof(AsyncTaskMethodBuilder) || (fi.FieldType.GetTypeInfo().IsGenericType&& fi.FieldType.GetGenericTypeDefinition() == typeof(AsyncTaskMethodBuilder <>)))) { if (isCompilerGeneratedField) { name = "__builder"; } builder = new AsyncStateMachineField(AsyncStateMachineFieldType.Builder, fi, name, internalName); builderType = fi.FieldType; } else if (isCompilerGeneratedField || !isCompilerGeneratedAsm) { #warning Need to solve problem when variables have the same name? e.g. "<myVar>5__1" and "<myVar>5__2". They must be in different scopes. localVariables.Add(new AsyncStateMachineField( AsyncStateMachineFieldType.LocalVariable, fi, name, internalName)); } else { inputArguments.Add(new AsyncStateMachineField( AsyncStateMachineFieldType.InputArgument, fi, name, internalName)); } } return(new AsyncStateMachineMetadata( stateMachineType, owner ?? default(AsyncStateMachineField), state ?? default(AsyncStateMachineField), builder ?? default(AsyncStateMachineField), inputArgs: inputArguments.ToArray(), localVars: localVariables.ToArray())); }