private static ReadStateMachineResult ReconstructStateMachine(AsyncMethodState state) { var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; // sm = new StateMachineType(); var assembly = Assembly.Load(state.StateMachineAssemblyName); var sm = Activator.CreateInstance(assembly.GetType(state.StateMachineTypeName)) as IAsyncStateMachine; // sm.builder = BuilderType.Create() var builderField = sm.BuilderField(); builderField.SetValue(sm, builderField.FieldType.GetMethod("Create").Invoke(null, new object[] { })); try { Expression.Lambda <Action>(Expression.Call(Expression.Field(Expression.Constant(sm), builderField), builderField.FieldType.GetMethod("SetStateMachine"), Expression.Constant(sm))).Compile().Invoke(); } catch (Exception e) { Console.WriteLine(e); throw; } // sm.builder.SetStateMachine(sm) // sm.state = i sm.GetType().GetField(state.StateNumber.MemberName).SetValue(sm, state.StateNumber.Value); // sm.<local> = <local_value> foreach (var local in state.Locals) { if (local.Value != null && local.Value.GetType() == typeof(SerializableTaskCompletionSource) && sm.GetType().GetField(local.MemberName, bf).FieldType.IsSubclassOf(typeof(Task))) { SerializableTaskCompletionSource stcs; if (((SerializableTaskCompletionSource)local.Value).IsCompleted) { stcs = (SerializableTaskCompletionSource)local.Value; } else { Immortal.InstanceProxy.Immortal.CallCache.Data.TryGetValue(((SerializableTaskCompletionSource)local.Value).SequenceNumber, out stcs); } var getAwaitableTaskMethod = typeof(SerializableTaskCompletionSource).GetMethods().FirstOrDefault(m => m.GetCustomAttributes(typeof(SerializableTaskCompletionSource.GetAwaitableTaskAttribute)).Any()); if (getAwaitableTaskMethod != null) { var genericGetAwaitabeTaskMethod = getAwaitableTaskMethod.MakeGenericMethod(stcs.ResultType.Type); var value = genericGetAwaitabeTaskMethod.Invoke(stcs, new object[] { }); sm.GetType().GetField(local.MemberName, bf).SetValue(sm, value); } } else { sm.GetType().GetField(local.MemberName, bf).SetValue(sm, local.Value); } } ReadStateMachineResult awaited; if (state.CurrentAwaiter.Value == null) { // sm.awaiter = new CheckpointSaveAwaiter() var awaiter = new CheckpointSaveAwaiter() { _result = 0 }; awaited = new ReadStateMachineResult() { AwaiterForAwaitingThisStateMachine = awaiter, LeafCheckpointSaveAwaiter = awaiter }; sm.GetType().GetField(state.CurrentAwaiter.MemberName, bf).SetValue(sm, awaiter); } else { // sm.awaiter = <nested state machine's awaiter> awaited = ReconstructStateMachine(state.CurrentAwaiter.Value); var awaiter = awaited.AwaiterForAwaitingThisStateMachine; sm.GetType().GetField(state.CurrentAwaiter.MemberName, bf).SetValue(sm, awaiter); } // sm.builder.AwaitOnCompleted(ref child_awaiter, ref sm); var varSm = Expression.Variable(sm.GetType(), "sm"); var varAwaiter = Expression.Variable(awaited.AwaiterForAwaitingThisStateMachine.GetType(), "awaiter"); var expression = Expression.Lambda <Action>(Expression.Block( new[] { varSm, varAwaiter }, Expression.Assign(varSm, Expression.Constant(sm)), Expression.Assign(varAwaiter, Expression.Constant(awaited.AwaiterForAwaitingThisStateMachine)), Expression.Call( Expression.Field(varSm, builderField), builderField.FieldType.GetMethod("AwaitOnCompleted").MakeGenericMethod(awaited.AwaiterForAwaitingThisStateMachine.GetType(), sm.GetType()), new Expression[] { varAwaiter, varSm }))); var lambda = expression.Compile(); if (state.CurrentAwaiter.Value == null) { awaited.LeafActionToStartWork = lambda; } else { lambda(); } // task = sm.Builder.Task var task = Expression.Lambda <Func <object> >(Expression.Property(Expression.Field(Expression.Constant(sm), builderField), builderField.FieldType.GetProperty("Task"))).Compile().Invoke(); // task.GetAwaiter(); var taskAwaiter = task.GetType().GetMethod("GetAwaiter").Invoke(task, new object[] { }); return(new ReadStateMachineResult { StateMachine = sm, Task = task as Task, AwaiterForAwaitingThisStateMachine = taskAwaiter, LeafActionToStartWork = awaited.LeafActionToStartWork, LeafCheckpointSaveAwaiter = awaited.LeafCheckpointSaveAwaiter }); }
private static ReadStateMachineResult ReconstructStateMachine(AsyncMethodState state) { var bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; // sm = new StateMachineType(); var sm = Activator.CreateInstance(state.StateMachineAssemblyName, state.StateMachineTypeName).Unwrap() as IAsyncStateMachine; // sm.builder = BuilderType.Create() var builderField = sm.BuilderField(); builderField.SetValue(sm, builderField.FieldType.GetMethod("Create").Invoke(null, new object[] { })); // sm.builder.SetStateMachine(sm) Expression.Lambda <Action>(Expression.Call(Expression.Field(Expression.Constant(sm), builderField), builderField.FieldType.GetMethod("SetStateMachine"), Expression.Constant(sm))).Compile().Invoke(); // sm.state = i sm.GetType().GetField(state.StateNumber.MemberName).SetValue(sm, state.StateNumber.Value); // sm.<local> = <local_value> foreach (var local in state.Locals) { sm.GetType().GetField(local.MemberName, bf).SetValue(sm, local.Value); } ReadStateMachineResult awaited; if (state.CurrentAwaiter.Value == null) { // sm.awaiter = new CheckpointSaveAwaiter() var awaiter = new CheckpointSaveAwaiter() { _result = 0 }; awaited = new ReadStateMachineResult() { AwaiterForAwaitingThisStateMachine = awaiter, LeafCheckpointSaveAwaiter = awaiter }; sm.GetType().GetField(state.CurrentAwaiter.MemberName, bf).SetValue(sm, awaiter); } else { // sm.awaiter = <nested state machine's awaiter> awaited = ReconstructStateMachine(state.CurrentAwaiter.Value); var awaiter = awaited.AwaiterForAwaitingThisStateMachine; sm.GetType().GetField(state.CurrentAwaiter.MemberName, bf).SetValue(sm, awaiter); } // sm.builder.AwaitOnCompleted(ref child_awaiter, ref sm); var varSm = Expression.Variable(sm.GetType(), "sm"); var varAwaiter = Expression.Variable(awaited.AwaiterForAwaitingThisStateMachine.GetType(), "awaiter"); var expression = Expression.Lambda <Action>(Expression.Block( new[] { varSm, varAwaiter }, Expression.Assign(varSm, Expression.Constant(sm)), Expression.Assign(varAwaiter, Expression.Constant(awaited.AwaiterForAwaitingThisStateMachine)), Expression.Call( Expression.Field(varSm, builderField), builderField.FieldType.GetMethod("AwaitOnCompleted").MakeGenericMethod(awaited.AwaiterForAwaitingThisStateMachine.GetType(), sm.GetType()), new Expression[] { varAwaiter, varSm }))); var lambda = expression.Compile(); if (state.CurrentAwaiter.Value == null) { awaited.LeafActionToStartWork = lambda; } else { lambda(); } // task = sm.Builder.Task var task = Expression.Lambda <Func <object> >(Expression.Property(Expression.Field(Expression.Constant(sm), builderField), builderField.FieldType.GetProperty("Task"))).Compile().Invoke(); // task.GetAwaiter(); var taskAwaiter = task.GetType().GetMethod("GetAwaiter").Invoke(task, new object[] { }); return(new ReadStateMachineResult { StateMachine = sm, Task = task as Task, AwaiterForAwaitingThisStateMachine = taskAwaiter, LeafActionToStartWork = awaited.LeafActionToStartWork, LeafCheckpointSaveAwaiter = awaited.LeafCheckpointSaveAwaiter }); }