internal ImmutableDispatchRuntime(DispatchRuntime dispatch)
        {
            this.authenticationBehavior = AuthenticationBehavior.TryCreate(dispatch);
            this.authorizationBehavior = AuthorizationBehavior.TryCreate(dispatch);
            this.concurrency = new ConcurrencyBehavior(dispatch);
            this.error = new ErrorBehavior(dispatch.ChannelDispatcher);
            this.enableFaults = dispatch.EnableFaults;
            this.inputSessionShutdownHandlers = EmptyArray<IInputSessionShutdown>.ToArray(dispatch.InputSessionShutdownHandlers);
            this.instance = new InstanceBehavior(dispatch, this);
            this.isOnServer = dispatch.IsOnServer;
            this.manualAddressing = dispatch.ManualAddressing;
            this.messageInspectors = EmptyArray<IDispatchMessageInspector>.ToArray(dispatch.MessageInspectors);
            this.requestReplyCorrelator = new RequestReplyCorrelator();
            this.securityImpersonation = SecurityImpersonationBehavior.CreateIfNecessary(dispatch);
            this.requireClaimsPrincipalOnOperationContext = dispatch.RequireClaimsPrincipalOnOperationContext;
            this.impersonateOnSerializingReply = dispatch.ImpersonateOnSerializingReply;
            this.terminate = TerminatingOperationBehavior.CreateIfNecessary(dispatch);
            this.thread = new ThreadBehavior(dispatch);
            this.validateMustUnderstand = dispatch.ValidateMustUnderstand;
            this.ignoreTransactionFlow = dispatch.IgnoreTransactionMessageProperty;
            this.transaction = TransactionBehavior.CreateIfNeeded(dispatch);
            this.receiveContextEnabledChannel = dispatch.ChannelDispatcher.ReceiveContextEnabled;
            this.sendAsynchronously = dispatch.ChannelDispatcher.SendAsynchronously;
            this.parameterInspectorCorrelationOffset = (dispatch.MessageInspectors.Count +
                dispatch.MaxCallContextInitializers);
            this.correlationCount = this.parameterInspectorCorrelationOffset + dispatch.MaxParameterInspectors;

            DispatchOperationRuntime unhandled = new DispatchOperationRuntime(dispatch.UnhandledDispatchOperation, this);

            if (dispatch.OperationSelector == null)
            {
                ActionDemuxer demuxer = new ActionDemuxer();
                for (int i = 0; i < dispatch.Operations.Count; i++)
                {
                    DispatchOperation operation = dispatch.Operations[i];
                    DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
                    demuxer.Add(operation.Action, operationRuntime);
                }

                demuxer.SetUnhandled(unhandled);
                this.demuxer = demuxer;
            }
            else
            {
                CustomDemuxer demuxer = new CustomDemuxer(dispatch.OperationSelector);
                for (int i = 0; i < dispatch.Operations.Count; i++)
                {
                    DispatchOperation operation = dispatch.Operations[i];
                    DispatchOperationRuntime operationRuntime = new DispatchOperationRuntime(operation, this);
                    demuxer.Add(operation.Name, operationRuntime);
                }

                demuxer.SetUnhandled(unhandled);
                this.demuxer = demuxer;
            }

            this.processMessage1 = new MessageRpcProcessor(this.ProcessMessage1);
            this.processMessage11 = new MessageRpcProcessor(this.ProcessMessage11);
            this.processMessage2 = new MessageRpcProcessor(this.ProcessMessage2);
            this.processMessage3 = new MessageRpcProcessor(this.ProcessMessage3);
            this.processMessage31 = new MessageRpcProcessor(this.ProcessMessage31);
            this.processMessage4 = new MessageRpcProcessor(this.ProcessMessage4);
            this.processMessage41 = new MessageRpcProcessor(this.ProcessMessage41);
            this.processMessage5 = new MessageRpcProcessor(this.ProcessMessage5);
            this.processMessage6 = new MessageRpcProcessor(this.ProcessMessage6);
            this.processMessage7 = new MessageRpcProcessor(this.ProcessMessage7);
            this.processMessage8 = new MessageRpcProcessor(this.ProcessMessage8);
            this.processMessage9 = new MessageRpcProcessor(this.ProcessMessage9);
            this.processMessageCleanup = new MessageRpcProcessor(this.ProcessMessageCleanup);
            this.processMessageCleanupError = new MessageRpcProcessor(this.ProcessMessageCleanupError);
        }
        internal void CheckIfTxCompletedAndUpdateAttached(ref MessageRpc rpc, bool isConcurrent)
        {
            if (rpc.Transaction.Current == null)
            {
                return;
            }

            lock (this.mutex)
            {
                if (!isConcurrent)
                {
                    if (this.shouldReleaseInstance)
                    {
                        this.shouldReleaseInstance = false;
                        if (rpc.Error == null) //we don't want to mask the initial error
                        {
                            rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true);
                            DiagnosticUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                            if (DiagnosticUtility.ShouldTraceInformation)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForAsyncAbort,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                        }
                    }

                    if (rpc.Transaction.IsCompleted || (rpc.Error != null))
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            if (rpc.Error != null)
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForError,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForError,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                            else
                            {
                                TraceUtility.TraceEvent(TraceEventType.Information,
                                                        TraceCode.TxCompletionStatusCompletedForAutocomplete,
                                                        SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAutocomplete,
                                                                     rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                     rpc.Operation.Name)
                                                        );
                            }
                        }

                        this.Attached = null;

                        if (!(waiting == null))
                        {
                            // tx processing requires failfast when state is inconsistent
                            DiagnosticUtility.FailFast("waiting should be null when resetting current");
                        }

                        this.current = null;
                    }
                    else
                    {
                        this.Attached = rpc.Transaction.Current;
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxCompletionStatusRemainsAttached,
                                                    SR.GetString(SR.TraceCodeTxCompletionStatusRemainsAttached,
                                                                 rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }
                else if (!this.pending.ContainsKey(rpc.Transaction.Current))
                {
                    //transaction has been asynchronously aborted
                    if (rpc.Error == null) //we don't want to mask the initial error
                    {
                        rpc.Error = TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true);
                        DiagnosticUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxCompletionStatusCompletedForAsyncAbort,
                                                    SR.GetString(SR.TraceCodeTxCompletionStatusCompletedForAsyncAbort,
                                                                 rpc.Transaction.Current.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }
            }
        }
 internal void CheckIfTxCompletedAndUpdateAttached(ref MessageRpc rpc, bool isConcurrent)
 {
     if (rpc.Transaction.Current != null)
     {
         lock (this.mutex)
         {
             if (!isConcurrent)
             {
                 if (this.shouldReleaseInstance)
                 {
                     this.shouldReleaseInstance = false;
                     if (rpc.Error == null)
                     {
                         rpc.Error = TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true);
                         DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                         if (DiagnosticUtility.ShouldTraceInformation)
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0009, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAsyncAbort", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                     }
                 }
                 if (rpc.Transaction.IsCompleted || (rpc.Error != null))
                 {
                     if (DiagnosticUtility.ShouldTraceInformation)
                     {
                         if (rpc.Error != null)
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0006, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForError", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                         else
                         {
                             TraceUtility.TraceEvent(TraceEventType.Information, 0xe0005, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAutocomplete", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                         }
                     }
                     this.Attached = null;
                     if (this.waiting != null)
                     {
                         DiagnosticUtility.FailFast("waiting should be null when resetting current");
                     }
                     this.current = null;
                 }
                 else
                 {
                     this.Attached = rpc.Transaction.Current;
                     if (DiagnosticUtility.ShouldTraceInformation)
                     {
                         TraceUtility.TraceEvent(TraceEventType.Information, 0xe000a, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusRemainsAttached", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                     }
                 }
             }
             else if (!this.pending.ContainsKey(rpc.Transaction.Current) && (rpc.Error == null))
             {
                 rpc.Error = TransactionBehavior.CreateFault(System.ServiceModel.SR.GetString("SFxTransactionAsyncAborted"), "TransactionAborted", true);
                 DiagnosticUtility.ExceptionUtility.TraceHandledException(rpc.Error, TraceEventType.Error);
                 if (DiagnosticUtility.ShouldTraceInformation)
                 {
                     TraceUtility.TraceEvent(TraceEventType.Information, 0xe0009, System.ServiceModel.SR.GetString("TraceCodeTxCompletionStatusCompletedForAsyncAbort", new object[] { rpc.Transaction.Current.TransactionInformation.LocalIdentifier, rpc.Operation.Name }));
                 }
             }
         }
     }
 }
        internal void ResolveTransaction(ref MessageRpc rpc)
        {
            if (rpc.Operation.HasDefaultUnhandledActionInvoker)
            {
                // we ignore unhandled operations
                return;
            }

            Transaction contextTransaction = null;

            //If we are inside a TransactedReceiveScope in workflow, then we need to look into the PPD and not the InstanceContext
            //to get the contextTransaction
            if (rpc.Operation.IsInsideTransactedReceiveScope)
            {
                // We may want to use an existing transaction for the instance.
                IInstanceTransaction instanceTransaction = rpc.Operation.Invoker as IInstanceTransaction;
                if (instanceTransaction != null)
                {
                    contextTransaction = instanceTransaction.GetTransactionForInstance(rpc.OperationContext);
                }

                if (contextTransaction != null)
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        TraceUtility.TraceEvent(TraceEventType.Information,
                                                TraceCode.TxSourceTxScopeRequiredUsingExistingTransaction,
                                                SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredUsingExistingTransaction,
                                                             contextTransaction.TransactionInformation.LocalIdentifier,
                                                             rpc.Operation.Name)
                                                );
                    }
                }
            }
            else
            {
                contextTransaction = this.GetInstanceContextTransaction(ref rpc);
            }

            Transaction transaction = null;

            try
            {
                transaction = TransactionMessageProperty.TryGetTransaction(rpc.Request);
            }
            catch (TransactionException e)
            {
                DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionUnmarshalFailed, e.Message), FaultCodeConstants.Codes.TransactionUnmarshalingFailed, false));
            }

            if (rpc.Operation.TransactionRequired)
            {
                if (transaction != null)
                {
                    if (this.isTransactedReceiveChannelDispatcher)
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsTransactedTransport,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactedTransport,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                    else
                    {
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsTransactionFlow,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsTransactionFlow,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }

                        if (PerformanceCounters.PerformanceCountersEnabled)
                        {
                            PerformanceCounters.TxFlowed(PerformanceCounters.GetEndpointDispatcher(), rpc.Operation.Name);
                        }

                        bool sameTransaction = false;
                        if (rpc.Operation.IsInsideTransactedReceiveScope)
                        {
                            sameTransaction = transaction.Equals(contextTransaction);
                        }
                        else
                        {
                            sameTransaction = transaction == contextTransaction;
                        }

                        if (!sameTransaction)
                        {
                            try
                            {
                                transaction = transaction.DependentClone(DependentCloneOption.RollbackIfNotComplete);
                            }
                            catch (TransactionException e)
                            {
                                DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                            }
                        }
                    }
                }
            }
            else
            {
                // We got a transaction from the ChannelHandler.
                // Transport is transacted.
                // But operation doesn't require the transaction, so no one ever will commit it.
                // Because of that we have to commit it here.
                if (transaction != null && this.isTransactedReceiveChannelDispatcher)
                {
                    try
                    {
                        if (null != rpc.TransactedBatchContext)
                        {
                            rpc.TransactedBatchContext.ForceCommit();
                            rpc.TransactedBatchContext = null;
                        }
                        else
                        {
                            TransactionInstanceContextFacet.Complete(transaction, null);
                        }
                    }
                    finally
                    {
                        transaction.Dispose();
                        transaction = null;
                    }
                }
            }

            InstanceContext context = rpc.InstanceContext;

            if (context.Transaction.ShouldReleaseInstance && !this.isConcurrent)
            {
                if (context.Behavior.ReleaseServiceInstanceOnTransactionComplete)
                {
                    context.ReleaseServiceInstance();
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        TraceUtility.TraceEvent(TraceEventType.Information,
                                                TraceCode.TxReleaseServiceInstanceOnCompletion,
                                                SR.GetString(SR.TraceCodeTxReleaseServiceInstanceOnCompletion,
                                                             contextTransaction.TransactionInformation.LocalIdentifier)
                                                );
                    }
                }

                context.Transaction.ShouldReleaseInstance = false;

                if (transaction == null || transaction == contextTransaction)
                {
                    rpc.Transaction.Current = contextTransaction;
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                }
                else
                {
                    contextTransaction = null;
                }
            }

            if (rpc.Operation.TransactionRequired)
            {
                if (transaction == null)
                {
                    if (contextTransaction != null)
                    {
                        transaction = contextTransaction;
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsAttachedTransaction,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsAttachedTransaction,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                    else
                    {
                        transaction = TransactionBehavior.CreateTransaction(this.isolation, this.timeout);
                        if (DiagnosticUtility.ShouldTraceInformation)
                        {
                            TraceUtility.TraceEvent(TraceEventType.Information,
                                                    TraceCode.TxSourceTxScopeRequiredIsCreateNewTransaction,
                                                    SR.GetString(SR.TraceCodeTxSourceTxScopeRequiredIsCreateNewTransaction,
                                                                 transaction.TransactionInformation.LocalIdentifier,
                                                                 rpc.Operation.Name)
                                                    );
                        }
                    }
                }

                if ((this.isolation != IsolationLevel.Unspecified) && (transaction.IsolationLevel != this.isolation))
                {
                    throw TraceUtility.ThrowHelperError(TransactionBehavior.CreateFault
                                                            (SR.GetString(SR.IsolationLevelMismatch2, transaction.IsolationLevel, this.isolation), FaultCodeConstants.Codes.TransactionIsolationLevelMismatch, false), rpc.Request);
                }

                rpc.Transaction.Current = transaction;
                rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Current, true);

                try
                {
                    rpc.Transaction.Clone = transaction.Clone();
                    if (rpc.Operation.IsInsideTransactedReceiveScope)
                    {
                        //It is because we want to synchronize the dispatcher processing of messages with the commit
                        //processing that is started by the completion of a TransactedReceiveScope. We need to make sure
                        //that all the dispatcher processing is done and we can do that by creating a blocking dependent clone and only
                        //completing it after all of the message processing is done for a given TransactionRpcFacet
                        rpc.Transaction.CreateDependentClone();
                    }
                }
                catch (ObjectDisposedException e)//transaction may be async aborted
                {
                    DiagnosticUtility.TraceHandledException(e, TraceEventType.Error);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(TransactionBehavior.CreateFault(SR.GetString(SR.SFxTransactionAsyncAborted), FaultCodeConstants.Codes.TransactionAborted, true));
                }

                rpc.InstanceContext.Transaction.AddReference(ref rpc, rpc.Transaction.Clone, false);

                rpc.OperationContext.TransactionFacet = rpc.Transaction;

                if (!rpc.Operation.TransactionAutoComplete)
                {
                    rpc.Transaction.SetIncomplete();
                }
            }
        }