protected virtual async Task ExecuteMessageHandlerAsync(
            EventArgs messageEventArgs,
            ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc,
            bool automaticFinalizationEnabled = true
            )
        {
            messageEventArgs.AssertNotNull(nameof(messageEventArgs));
            receivedItemHandlerAsyncDelegateFunc.AssertNotNull(nameof(receivedItemHandlerAsyncDelegateFunc));

            AzureServiceBusReceivedItem <TUniqueIdentifier, TPayload> azureServiceBusReceivedItem = null;

            //FIRST attempt to convert the Message into an AzureServiceBus Received Item....
            try
            {
                //Initialize the MessageHandler facade for processing the Azure Service Bus message...
                azureServiceBusReceivedItem = await CreateReceivedItemAsync(
                    messageEventArgs,
                    //Force Dead-lettering if there is any issue with initialization!
                    true
                    ).AssertNotNull(nameof(azureServiceBusReceivedItem));
            }
            catch (Exception exc)
            {
                var messageException = new Exception("The message could not be correctly initialized due to unexpected exception." +
                                                     " It must be Dead lettered to prevent blocking of the Service Bus as it will never be" +
                                                     " processed successfully.", exc);

                this.Options.ErrorHandlerCallback?.Invoke(messageException);
            }

            //IF the Received Item is successfully initialized then process it!
            if (azureServiceBusReceivedItem != null)
            {
                try
                {
                    //Execute the delegate to handle/process the published item...
                    await receivedItemHandlerAsyncDelegateFunc(azureServiceBusReceivedItem).ConfigureAwait(false);

                    //If necessary, we need to Finalize the item with Azure Service Bus (Complete/Abandon) based on the Status returned on the item!
                    if (automaticFinalizationEnabled && !azureServiceBusReceivedItem.IsStatusFinalized)
                    {
                        await azureServiceBusReceivedItem.SendFinalizedStatusToAzureServiceBusAsync().ConfigureAwait(false);
                    }
                }
                catch (Exception exc)
                {
                    this.Options.ErrorHandlerCallback?.Invoke(exc);

                    //Always attempt to Reject/Abandon the message if any unhandled exceptions are thrown...
                    if (!azureServiceBusReceivedItem.IsStatusFinalized)
                    {
                        //Finalize the status as set by the Delegate function if it's not already Finalized!
                        //NOTE: We ALWAYS do this even if autoMessageFinalizationEnabled is false to prevent BLOCKING and risk of Infinite Loops...
                        await azureServiceBusReceivedItem.SendFinalizedStatusToAzureServiceBusAsync().ConfigureAwait(false);
                    }
                }
            }
        }
        public virtual Task StartReceivingAsync(
            ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc,
            CancellationToken cancellationToken = default
            )
        {
            if (this.IsProcessing)
            {
                return(Task.CompletedTask);
            }

            return(StartReceivingInternalAsync(receivedItemHandlerAsyncDelegateFunc, cancellationToken: cancellationToken));
        }
        protected virtual async Task StartReceivingInternalAsync(
            ReceivedItemHandlerAsyncDelegate receivedItemHandlerAsyncDelegateFunc,
            bool autoMessageFinalizationEnabled = true,
            CancellationToken cancellationToken = default
            )
        {
            //Ensure we are set to have started Processing...
            this.IsProcessing = true;

            //Validate handler and other references...
            receivedItemHandlerAsyncDelegateFunc.AssertNotNull(nameof(receivedItemHandlerAsyncDelegateFunc));

            //Complete full Handler Initialization with provided options, etc...
            //NOTE: IF FIFO Processing is enabled we use Azure Session Processor; otherwise default Processor is used.
            if (Options.FifoEnforcedReceivingEnabled)
            {
                if (this.ServiceBusSessionProcessor == null)
                {
                    this.ServiceBusSessionProcessor = GetAzureServiceBusSessionProcessor();

                    this.ServiceBusSessionProcessor.ProcessMessageAsync += async(messageEventArgs) =>
                    {
                        await ExecuteMessageHandlerAsync(
                            //Note: We Must use the MessageSession as the Client for processing messages with the Locked Session!
                            messageEventArgs,
                            receivedItemHandlerAsyncDelegateFunc,
                            autoMessageFinalizationEnabled
                            ).ConfigureAwait(false);
                    };

                    //Wire up the Error/Exception Handler...
                    this.ServiceBusSessionProcessor.ProcessErrorAsync += ExceptionReceivedHandlerAsync;
                }

                //Kick off processing!!!
                if (!this.ServiceBusSessionProcessor.IsProcessing)
                {
                    await this.ServiceBusSessionProcessor.StartProcessingAsync(cancellationToken);
                }
            }
            else
            {
                if (this.ServiceBusProcessor == null)
                {
                    this.ServiceBusProcessor = GetAzureServiceBusProcessor();

                    //Wire up the Handler...
                    this.ServiceBusProcessor.ProcessMessageAsync += async(messageEventArgs) =>
                    {
                        await ExecuteMessageHandlerAsync(
                            messageEventArgs,
                            receivedItemHandlerAsyncDelegateFunc,
                            autoMessageFinalizationEnabled
                            ).ConfigureAwait(false);
                    };

                    //Wire up the Error/Exception Handler...
                    this.ServiceBusProcessor.ProcessErrorAsync += ExceptionReceivedHandlerAsync;
                }

                //Kick off processing!!!
                if (!this.ServiceBusProcessor.IsProcessing)
                {
                    await this.ServiceBusProcessor.StartProcessingAsync(cancellationToken);
                }
            }
        }