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);
        }
Example #2
0
        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));
        }
Example #3
0
        private object GetExportedValue(ComposablePart part, ExportDefinition export)
        {
            ThrowIfDisposed();
            EnsureRunning();

            return(CompositionServices.GetExportedValueFromComposedPart(ImportEngine, part, export));
        }
Example #4
0
 /// <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);
     }
 }
Example #5
0
        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));
        }
Example #6
0
        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);
        }
Example #7
0
        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();
        }