public Task <T> ExecuteOrchestration <T>(OrchestrationInstance instance, FakeOrchestrationContext parentContext,
                                                 string name, string version, object input)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            return(ExecuteOrchestration <T>(instance, parentContext.TaskActivityExecutor, parentContext.Clock, name,
                                            version, input));
        }
        public async Task <T> ExecuteOrchestration <T>(OrchestrationInstance instance,
                                                       FakeTaskActivityExecutor taskActivityExecutor,
                                                       FakeOrchestrationClock clock, string name, string version, object input)
        {
            string actualVersion = version;

            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            if (string.IsNullOrWhiteSpace(instance.InstanceId))
            {
                instance.InstanceId = Guid.NewGuid().ToString("N");
            }

            if (string.IsNullOrWhiteSpace(instance.ExecutionId))
            {
                instance.ExecutionId = Guid.NewGuid().ToString("N");
            }

            if (currentExecutions.ContainsKey(instance.InstanceId))
            {
                throw new OrchestrationFrameworkException("Orchestration instance with id '" + instance.InstanceId +
                                                          "' already running.");
            }

            T result = default(T);
            FakeOrchestrationContext context;

            do
            {
                context = new FakeOrchestrationContext(scheduler, instance, taskActivityExecutor, this, clock);
                result  = await Execute <T>(context, name, actualVersion, input);

                if (context.StartNew)
                {
                    actualVersion = context.NewVersion ?? actualVersion;

                    while (clock.HasPendingTimers || taskActivityExecutor.HasPendingExecutions)
                    {
                        // wait for pending tasks to complete before starting new generation
                        await Task.Delay(10);
                    }

                    input = context.ContinueAsNewInput;
                    instance.ExecutionId = Guid.NewGuid().ToString("N");
                }
            } while (context.StartNew);

            return(result);
        }
        async Task <T> Execute <T>(FakeOrchestrationContext context, string name, string version, object input)
        {
            OrchestrationInstance  instance = context.OrchestrationInstance;
            SynchronizationContext prevCtx  = SynchronizationContext.Current;

            try
            {
                TaskOrchestration definition = orchestrationObjectManager.GetObject(name, version);
                if (definition == null)
                {
                    throw new OrchestrationFrameworkException("Orchestration not found");
                }

                string        serializedInput      = dataConverter.Serialize(input);
                Task <string> serializedResultTask = definition.Execute(context, serializedInput);
                currentExecutions.Add(instance.InstanceId, definition);

                string serializedResult = null;
                try
                {
                    serializedResult = await serializedResultTask;
                }
                catch (OrchestrationFailureException e)
                {
                    Exception cause = Utils.RetrieveCause(e.Details, dataConverter);
                    var       subOrchestrationFailedException = new SubOrchestrationFailedException(0, 0, name, version,
                                                                                                    e.Message, cause);
                    throw subOrchestrationFailedException;
                }
                catch (Exception e)
                {
                    var subOrchestrationFailedException = new SubOrchestrationFailedException(0, 0, name, version,
                                                                                              e.Message, e);
                    throw subOrchestrationFailedException;
                }

                return(dataConverter.Deserialize <T>(serializedResult));
            }
            finally
            {
                SynchronizationContext.SetSynchronizationContext(prevCtx);
                TaskOrchestration orchestration = null;
                if (currentExecutions.TryGetValue(instance.InstanceId, out orchestration))
                {
                    currentExecutions.Remove(instance.InstanceId);
                    completedExecutions.Add(instance, orchestration);
                }
            }
        }