protected Task <TResult> DurablyInvoke <TResult>(DurableAttribute durableAttribute, IInvocation invocation)
        {
            if (!invocation.Method.ReturnType.IsAssignableTo <Task>())
            {
                throw new DurableInvocationException(
                          $"Method {invocation.Method} has a return type of {invocation.Method.ReturnType} but its application of {durableAttribute.GetType().Name} requries its return type be of type {typeof(Task)}."
                          );
            }

            var baseUrl             = Context.Value.FunctionContext?.BaseUrl;
            var functionName        = durableAttribute.GetFunctionName();
            var methodSpecificaiton = this.typeSerivce.Value.GetMethodSpecification(invocation.Method);
            var instanceId          = durableAttribute.IsSingleInstance ? durableAttribute.InstanceId ?? methodSpecificaiton : null;
            var methodArguments     = invocation.Method.GetParameters().Zip(invocation.Arguments, (a, b) => (a.Name, Value: b)).ToDictionary();

            var durableContext = new DurableContext {
                OrchestrationContext = Context.Value.OrchestrationContext,
                OrchestrationClient  = Context.Value.OrchestrationClient,
                FunctionContext      = new FunctionContext {
                    BaseUrl             = baseUrl,
                    FunctionName        = functionName,
                    InstanceId          = instanceId,
                    MethodSpecification = methodSpecificaiton,
                    Instance            = invocation.InvocationTarget,
                    Arguments           = methodArguments
                }
            };

            return(Context.Value?.FunctionContext?.MethodSpecification == methodSpecificaiton ||
                   durableAttribute.ExternalOrchestratorUrlOrAppSetting.IsNullOrWhiteSpace() ?
                   this.DurablyInvokeInternally <TResult>(durableAttribute, durableContext) :
                   this.DurablyInvokeExternally <TResult>(durableAttribute, durableContext));
        }
        protected async Task <TResult> DurablyInvokeExternally <TResult>(DurableAttribute durableAttribute, DurableContext durableContext)
        {
            const string eventName = "external-durable-invocation-complete";

            durableContext.FunctionContext.CallbackUrl = durableContext.OrchestrationClient.CreateHttpManagementPayload(durableContext.OrchestrationContext.InstanceId).SendEventPostUri.Replace("{eventName}", eventName);
            var url = this.configuration.GetValue <string>(durableAttribute.ExternalOrchestratorUrlOrAppSetting) ?? durableAttribute.ExternalOrchestratorUrlOrAppSetting;

            await durableContext.OrchestrationContext.CallHttpAsync(
                HttpMethod.Post,
                new Uri(url),
                durableContext.FunctionContext.ToJson()
                );

            return(await durableContext.OrchestrationContext.WaitForExternalEvent <TResult>(eventName));
        }
 protected async Task <TResult> DurablyInvokeInternally <TResult>(DurableAttribute durableAttribute, DurableContext durableContext)
 {
     return(await durableAttribute.Invoke <TResult>(durableContext));
 }