Esempio n. 1
0
        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
            });
        }
Esempio n. 2
0
    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
        });
    }