private CompositionResult TryPreviewImportsStateMachine(PartManager partManager, ComposablePart part, AtomicComposition atomicComposition) { var result = CompositionResult.SucceededResult; if (partManager.State == ImportState.ImportsPreviewing) { // We shouldn't nomally ever hit this case but if we do // then we should just error with a cycle error. return(new CompositionResult(ErrorBuilder.CreatePartCycle(part))); } // Transition from NoImportsStatisified to ImportsPreviewed if (partManager.State == ImportState.NoImportsSatisfied) { partManager.State = ImportState.ImportsPreviewing; var requiredImports = part.ImportDefinitions.Where(IsRequiredImportForPreview); // If this atomicComposition gets rolledback for any reason we need to reset our state atomicComposition.AddRevertActionAllowNull(() => partManager.State = ImportState.NoImportsSatisfied); result = result.MergeResult( this.TrySatisfyImportSubset(partManager, requiredImports, atomicComposition)); if (!result.Succeeded) { partManager.State = ImportState.NoImportsSatisfied; return(result); } partManager.State = ImportState.ImportsPreviewed; } return(result); }
private CompositionResult TrySatisfyImportsStateMachine(PartManager partManager, ComposablePart part) { var result = CompositionResult.SucceededResult; while (partManager.State < ImportState.Composed) { var previousState = partManager.State; switch (partManager.State) { // "ed" states which represent a some sort of steady state and will // attempt to do a state transition case ImportState.NoImportsSatisfied: case ImportState.ImportsPreviewed: { partManager.State = ImportState.PreExportImportsSatisfying; var prereqImports = part.ImportDefinitions.Where(import => import.IsPrerequisite); result = result.MergeResult( this.TrySatisfyImportSubset(partManager, prereqImports, null)); partManager.State = ImportState.PreExportImportsSatisfied; break; } case ImportState.PreExportImportsSatisfied: { partManager.State = ImportState.PostExportImportsSatisfying; var requiredImports = part.ImportDefinitions.Where(import => !import.IsPrerequisite); result = result.MergeResult( this.TrySatisfyImportSubset(partManager, requiredImports, null)); partManager.State = ImportState.PostExportImportsSatisfied; break; } case ImportState.PostExportImportsSatisfied: { partManager.State = ImportState.ComposedNotifying; partManager.ClearSavedImports(); result = result.MergeResult(partManager.TryOnComposed()); partManager.State = ImportState.Composed; break; } // "ing" states which represent some sort of cycle // These state should always return, error or not, instead of breaking case ImportState.ImportsPreviewing: { // We shouldn't nomally ever hit this case but if we do // then we should just error with a cycle error. return(new CompositionResult(ErrorBuilder.CreatePartCycle(part))); } case ImportState.PreExportImportsSatisfying: case ImportState.PostExportImportsSatisfying: { if (InPrerequisiteLoop()) { return(result.MergeError(ErrorBuilder.CreatePartCycle(part))); } // Cycles in post export imports are allowed so just return in that case return(result); } case ImportState.ComposedNotifying: { // We are currently notifying so don't notify again just return return(result); } } // if an error occured while doing a state transition if (!result.Succeeded) { // revert to the previous state and return the error partManager.State = previousState; return(result); } } return(result); }