public void Compose(CompositionBatch batch) { ThrowIfDisposed(); EnsureRunning(); Requires.NotNull(batch, nameof(batch)); // Quick exit test can be done prior to cloning since it's just an optimization, not a // change in behavior if ((batch.PartsToAdd.Count == 0) && (batch.PartsToRemove.Count == 0)) { return; } CompositionResult result = CompositionResult.SucceededResult; // Get updated parts list and a cloned batch var newParts = GetUpdatedPartsList(ref batch); // Allow only recursive calls from the import engine to see the changes until // they've been verified ... using (var atomicComposition = new AtomicComposition()) { // Don't allow reentrant calls to compose during previewing to prevent // corrupted state. if (_currentlyComposing) { throw new InvalidOperationException(SR.ReentrantCompose); } _currentlyComposing = true; try { // In the meantime recursive calls need to be able to see the list as well atomicComposition.SetValue(this, newParts); // Recompose any existing imports effected by the these changes first so that // adapters, resurrected parts, etc. can all play their role in satisfying // imports for added parts Recompose(batch, atomicComposition); // Ensure that required imports can be satisfied foreach (ComposablePart part in batch.PartsToAdd) { // collect the result of previewing all the adds in the batch try { ImportEngine.PreviewImports(part, atomicComposition); } catch (ChangeRejectedException ex) { result = result.MergeResult(new CompositionResult(ex.Errors)); } } result.ThrowOnErrors(atomicComposition); // Complete the new parts since they passed previewing.` using (_lock.LockStateForWrite()) { _parts = newParts; } atomicComposition.Complete(); } finally { _currentlyComposing = false; } } // Satisfy Imports // - Satisfy imports on all newly added component parts foreach (ComposablePart part in batch.PartsToAdd) { result = result.MergeResult(CompositionServices.TryInvoke(() => ImportEngine.SatisfyImports(part))); } // return errors result.ThrowOnErrors(); }
public void Compose(CompositionBatch batch) { this.ThrowIfDisposed(); this.EnsureRunning(); Requires.NotNull(batch, "batch"); // Quick exit test can be done prior to cloning since it's just an optimization, not a // change in behavior if ((batch.PartsToAdd.Count == 0) && (batch.PartsToRemove.Count == 0)) { return; } CompositionResult result = CompositionResult.SucceededResult; // Clone the batch, so that the external changes wouldn't happen half-way thorugh compose // NOTE : this does not guarantee the atomicity of cloning, which is not the goal anyway, // rather the fact that all subsequent calls will deal with an unchanging batch batch = new CompositionBatch(batch.PartsToAdd, batch.PartsToRemove); var newParts = GetUpdatedPartsList(batch); // Allow only recursive calls from the import engine to see the changes until // they've been verified ... using (var atomicComposition = new AtomicComposition()) { // Don't allow reentrant calls to compose during previewing to prevent // corrupted state. if (this._currentlyComposing) { throw new InvalidOperationException(Strings.ReentrantCompose); } this._currentlyComposing = true; try { // In the meantime recursive calls need to be able to see the list as well atomicComposition.SetValue(this, newParts); // Recompose any existing imports effected by the these changes first so that // adapters, resurrected parts, etc. can all play their role in satisfying // imports for added parts this.Recompose(batch, atomicComposition); // Ensure that required imports can be satisfied foreach (ComposablePart part in batch.PartsToAdd) { // collect the result of previewing all the adds in the batch try { this._importEngine.PreviewImports(part, atomicComposition); } catch (ChangeRejectedException ex) { result = result.MergeResult(new CompositionResult(ex.Errors)); } } result.ThrowOnErrors(atomicComposition); // Complete the new parts since they passed previewing.` using (this._lock.LockStateForWrite()) { this._parts = newParts; } atomicComposition.Complete(); } finally { this._currentlyComposing = false; } } // Satisfy Imports // - Satisfy imports on all newly added component parts foreach (ComposablePart part in batch.PartsToAdd) { result = result.MergeResult(CompositionServices.TryInvoke(() => this._importEngine.SatisfyImports(part))); } // return errors result.ThrowOnErrors(); }