/// <summary>
                /// Initializes a new instance of the <see cref="StateLoader"/> class.
                /// </summary>
                /// <param name="reader">The reader.</param>
                /// <param name="engine">The engine.</param>
                public StateLoader(IStateReader reader, CoreReactiveEngine engine)
                {
                    Debug.Assert(reader != null, "Reader should not be null.");
                    Debug.Assert(engine != null, "Engine should not be null.");

                    _reader               = reader;
                    _engine               = engine;
                    _registry             = new ShadowRegistry();
                    _placeholderMitigator = new PlaceholderMitigator(engine);
                }
            /// <summary>
            /// Try to invoke the specified <paramref name="action"/> and handle any exception that occurs.
            /// If an exception occurs and <paramref name="shouldMitigate"/> is true, the specified <paramref name="mitigator"/> is used to apply a mitigation.
            /// </summary>
            /// <param name="action">The action to try.</param>
            /// <param name="entity">The entity being loaded/mitigated.</param>
            /// <param name="shouldMitigate">true if errors should be mitigated; otherwise, false.</param>
            /// <param name="mitigator">The mitigator to use if the failed action should be mitigated.</param>
            private void TryMitigate(Action action, ReactiveEntity entity, bool shouldMitigate, ReactiveEntityRecoveryFailureMitigator mitigator)
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    var error = new EntityLoadFailedException(entity.Uri, entity.Kind, ex);

                    if (shouldMitigate && Parent._engine.OnEntityLoadFailed(entity.Uri, entity, entity.Kind, error, out ReactiveEntityRecoveryFailureMitigation mitigation))
                    {
                        var trace = Parent.TraceSource;

                        trace.Mitigation_Execute(entity.Uri, mitigation);

#pragma warning disable IDE0079 // Remove unnecessary suppression.
#pragma warning disable CA1031  // Do not catch general exception types. (Protecting against engine unavailability; last resort mitigation with tracing of errors.)

                        try
                        {
                            if (!mitigator.DoMitigate(entity, mitigation))
                            {
                                trace.Mitigation_NotAccepted(mitigation, entity.Uri, ex);
                            }
                        }
                        catch (Exception mx)
                        {
                            trace.Mitigation_Failure(mitigation, entity.Uri, mx);
                        }

#pragma warning restore CA1031
#pragma warning restore IDE0079

                        // For this implementation, whenever a mitigation occurs, we will throw a
                        // bail out exception. This is to prevent further processing of the
                        // 'normal' recovery process from throwing additional errors that will
                        // trigger additional mitigations. An unfortunate consequence is that the
                        // mitigations must ensure all steps that would have occurred in the
                        // 'normal' recovery process occur in the mitigation (esp. for things
                        // mitigations like `Regenerate`. Right now, this is not a problem, as the
                        // steps being mitigated are late in the recovery process.
                        throw new MitigationBailOutException();
                    }

                    // This may result in a second call to the `EntityLoadFailed` event.
                    throw;
                }
            }