private object GetExportedValue(CatalogPart part, ExportDefinition export, bool isSharedPart) { ThrowIfDisposed(); EnsureRunning(); Assumes.NotNull(part, export); // We don't protect against thread racing here, as "importsSatisfied" is merely an optimization // if two threads satisfy imports twice, the results is the same, just the perf hit is heavier. bool importsSatisfied = part.ImportsSatisfied; ImportEngine importEngine = importsSatisfied ? null : _importEngine; object exportedValue = CompositionServices.GetExportedValueFromComposedPart( importEngine, part.Part, export); if (!importsSatisfied) { // and set "ImportsSatisfied" to true part.ImportsSatisfied = true; } // Only hold conditional references for recomposable non-shared parts because we are // already holding strong references to the shared parts. if (exportedValue != null && !isSharedPart && part.Part.IsRecomposable()) { PreventPartCollection(exportedValue, part.Part); } return(exportedValue); }
private static ImportDefinition BuildImportDefinition(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (metadataViewType == null) { throw new ArgumentNullException(nameof(metadataViewType)); } if (contractName == null) { throw new ArgumentNullException(nameof(contractName)); } IEnumerable <KeyValuePair <string, Type> > requiredMetadata = CompositionServices.GetRequiredMetadata(metadataViewType); IDictionary <string, object?> metadata = CompositionServices.GetImportMetadata(type, null); string?requiredTypeIdentity = null; if (type != typeof(object)) { requiredTypeIdentity = AttributedModelServices.GetTypeIdentity(type); } return(new ContractBasedImportDefinition(contractName, requiredTypeIdentity, requiredMetadata, cardinality, false, true, CreationPolicy.Any, metadata)); }
private object GetExportedValue(ComposablePart part, ExportDefinition export) { ThrowIfDisposed(); EnsureRunning(); return(CompositionServices.GetExportedValueFromComposedPart(ImportEngine, part, export)); }
/// <summary> /// Raises the <see cref="ExportsChanging"/> event. /// </summary> /// <param name="e"> /// An <see cref="ExportsChangeEventArgs"/> containing the data for the event. /// </param> protected virtual void OnExportsChanging(ExportsChangeEventArgs e) { EventHandler<ExportsChangeEventArgs> changingEvent = this.ExportsChanging; if (changingEvent != null) { CompositionResult result = CompositionServices.TryFire(changingEvent, this, e); result.ThrowOnErrors(e.AtomicComposition); } }
private static ImportDefinition BuildImportDefinition(Type type, Type metadataViewType, string contractName, ImportCardinality cardinality) { Assumes.NotNull(type, metadataViewType, contractName); IEnumerable <KeyValuePair <string, Type> > requiredMetadata = CompositionServices.GetRequiredMetadata(metadataViewType); string requiredTypeIdentity = null; if (type != typeof(object)) { requiredTypeIdentity = AttributedModelServices.GetTypeIdentity(type); } return(new ContractBasedImportDefinition(contractName, requiredTypeIdentity, requiredMetadata, cardinality, false, true, CreationPolicy.Any)); }
private object GetExportedValue(ComposablePart part, ExportDefinition export, bool isSharedPart) { this.ThrowIfDisposed(); this.EnsureRunning(); Assumes.NotNull(part, export); object exportedValue = CompositionServices.GetExportedValueFromComposedPart( this._importEngine, part, export); // Only hold conditional references for recomposable non-shared parts because we are // already holding strong references to the shared parts. if (exportedValue != null && !isSharedPart && part.IsRecomposable()) { SetConditionalReferenceForRecomposablePart(exportedValue, part); } return(exportedValue); }
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(); }