Example #1
0
        /// <summary>
        ///     Sets the imports of the specified composable part exactly once and they will not
        ///     ever be recomposed.
        /// </summary>
        /// <param name="part">
        ///     The <see cref="ComposablePart"/> to set the imports.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="part"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="CompositionException">
        ///     An error occurred during composition. <see cref="CompositionException.Errors"/> will
        ///     contain a collection of errors that occurred.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     The <see cref="ICompositionService"/> has been disposed of.
        /// </exception>
        public void SatisfyImportsOnce(ComposablePart part)
        {
            this.ThrowIfDisposed();

            if (this._importEngine == null)
            {
                ImportEngine importEngine = new ImportEngine(this, this._isThreadSafe);

                lock (this._lock)
                {
                    if (this._importEngine == null)
                    {
                        Thread.MemoryBarrier();
                        this._importEngine = importEngine;
                        importEngine       = null;
                    }
                }

                if (importEngine != null)
                {
                    importEngine.Dispose();
                }
            }

            this._importEngine.SatisfyImportsOnce(part);
        }
        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 #3
0
        public void PreviewImports_Unsuccessful_NoAtomicComposition_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value");
            var importer = PartFactory.CreateImporter(import);

            ExceptionAssert.Throws<CompositionException>(() =>
                engine.PreviewImports(importer, null));

            exportProvider.AddExport("Value", 22);
            exportProvider.AddExport("Value", 23);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
Example #4
0
        public CompositionContainer(ComposablePartCatalog catalog, bool isThreadSafe, params ExportProvider[] providers)
        {
            this._importEngine       = new ImportEngine(this, isThreadSafe);
            this._partExportProvider = new ComposablePartExportProvider(isThreadSafe);
            this._partExportProvider.SourceProvider = this;
            this._providers = new ReadOnlyCollection <ExportProvider>(providers != null ? (ExportProvider[])providers.Clone() : new ExportProvider[0]);

            List <ExportProvider> providerList = new List <ExportProvider>();

            providerList.Add(this._partExportProvider);

            if (catalog != null)
            {
                this._catalogExportProvider = new CatalogExportProvider(catalog, isThreadSafe);
                this._catalogExportProvider.SourceProvider = this;

                providerList.Add(this._catalogExportProvider);
            }

            foreach (var provider in this._providers)
            {
                if (provider == null)
                {
                    throw ExceptionBuilder.CreateContainsNullElement("providers");
                }
                providerList.Add(provider);
            }

            // we only build the aggregating provider if necessary - that is, if we have more than one provider to aggregate
            if (providerList.Count > 1)
            {
                this._aggregatingExportProvider = new AggregateExportProvider(providerList);
                this._rootProvider = this._aggregatingExportProvider;
            }
            else
            {
                Assumes.IsTrue(providerList.Count == 1);
                this._rootProvider = providerList[0];
            }

            this._rootProvider.ExportsChanged  += this.OnExportsChangedInternal;
            this._rootProvider.ExportsChanging += this.OnExportsChangingInternal;
        }
        internal static object GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)
        {
            try
            {
                engine.SatisfyImports(part);
            }
            catch (CompositionException ex)
            {
                throw ExceptionBuilder.CreateCannotGetExportedValue(part, definition, ex);
            }

            try
            {
                return(part.GetExportedValue(definition));
            }
            catch (ComposablePartException ex)
            {
                throw ExceptionBuilder.CreateCannotGetExportedValue(part, definition, ex);
            }
        }
        /// <summary>
        ///     Sets the imports of the specified composable part exactly once and they will not
        ///     ever be recomposed.
        /// </summary>
        /// <param name="part">
        ///     The <see cref="ComposablePart"/> to set the imports.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="part"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="CompositionException">
        ///     An error occurred during composition. <see cref="CompositionException.Errors"/> will
        ///     contain a collection of errors that occurred.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///     The <see cref="ICompositionService"/> has been disposed of.
        /// </exception>
        public void SatisfyImportsOnce(ComposablePart part)
        {
            ThrowIfDisposed();

            if (_importEngine == null)
            {
                ImportEngine?importEngine = new ImportEngine(this, _compositionOptions);

                lock (_lock)
                {
                    if (_importEngine == null)
                    {
                        Thread.MemoryBarrier();
                        _importEngine = importEngine;
                        importEngine  = null;
                    }
                }
                importEngine?.Dispose();
            }
            _importEngine.SatisfyImportsOnce(part);
        }
Example #7
0
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_isDisposed)
                {
                    bool         disposeLock  = false;
                    ImportEngine importEngine = null;
                    try
                    {
                        using (_lock.LockStateForWrite())
                        {
                            if (!_isDisposed)
                            {
                                importEngine  = _importEngine;
                                _importEngine = null;

                                _sourceProvider = null;
                                _isDisposed     = true;
                                disposeLock     = true;
                            }
                        }
                    }
                    finally
                    {
                        if (importEngine != null)
                        {
                            importEngine.Dispose();
                        }

                        if (disposeLock)
                        {
                            _lock.Dispose();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!this._isDisposed)
                {
                    bool         disposeLock     = false;
                    ImportEngine oldImportEngine = null;
                    try
                    {
                        using (this._lock.LockStateForWrite())
                        {
                            if (!this._isDisposed)
                            {
                                oldImportEngine      = this._importEngine;
                                this._importEngine   = null;
                                this._sourceProvider = null;
                                this._isDisposed     = true;
                                disposeLock          = true;
                            }
                        }
                    }
                    finally
                    {
                        if (oldImportEngine != null)
                        {
                            oldImportEngine.Dispose();
                        }

                        if (disposeLock)
                        {
                            this._lock.Dispose();
                        }
                    }
                }
            }
        }
Example #9
0
        public void PreviewImports_Successful_AtomicComposition_Completeted_ShouldBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value");
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 21);

            using (var atomicComposition = new AtomicComposition())
            {
                engine.PreviewImports(importer, atomicComposition);
                atomicComposition.Complete();
            }

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.AddExport("Value", 22));

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.RemoveExport("Value"));

            GC.KeepAlive(importer);
        }
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!this._isDisposed)
                {
                    bool disposeLock = false;
                    INotifyComposablePartCatalogChanged catalogToUnsubscribeFrom = null;
                    HashSet <IDisposable> partsToDispose = null;
                    ImportEngine          importEngine   = null;
                    ExportProvider        sourceProvider = null;
                    try
                    {
                        using (this._lock.LockStateForWrite())
                        {
                            if (!this._isDisposed)
                            {
                                catalogToUnsubscribeFrom = this._catalog as INotifyComposablePartCatalogChanged;
                                this._catalog            = null;

                                sourceProvider       = this._sourceProvider;
                                this._sourceProvider = null;

                                importEngine       = this._importEngine;
                                this._importEngine = null;

                                partsToDispose = this._partsToDispose;
                                this._gcRoots  = null;

                                disposeLock      = true;
                                this._isDisposed = true;
                            }
                        }
                    }
                    finally
                    {
                        if (catalogToUnsubscribeFrom != null)
                        {
                            catalogToUnsubscribeFrom.Changing -= this.OnCatalogChanging;
                        }

                        if (sourceProvider != null)
                        {
                            sourceProvider.ExportsChanging -= this.OnExportsChangingInternal;
                        }

                        if (importEngine != null)
                        {
                            importEngine.Dispose();
                        }

                        if (partsToDispose != null)
                        {
                            foreach (var part in partsToDispose)
                            {
                                part.Dispose();
                            }
                        }

                        if (disposeLock)
                        {
                            this._lock.Dispose();
                        }
                    }
                }
            }
        }
Example #11
0
        public void SatisfyImports_Recomposable_Unregister_ValueShouldChangeOnce()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            exportProvider.AddExport("Value", 21);

            var import = ImportDefinitionFactory.Create("Value", true);
            var importer = PartFactory.CreateImporter(import);

            engine.SatisfyImports(importer);

            Assert.AreEqual(21, importer.GetImport(import));

            exportProvider.ReplaceExportValue("Value", 42);

            Assert.AreEqual(42, importer.GetImport(import), "Value should change!");

            engine.ReleaseImports(importer, null);

            exportProvider.ReplaceExportValue("Value", 666);

            Assert.AreEqual(42, importer.GetImport(import), "Value should not change!");

            GC.KeepAlive(importer);
        }
 public PartManager(ImportEngine importEngine, ComposablePart part)
 {
     _importEngine = importEngine;
     _part         = part;
 }
 public EngineContext(ImportEngine importEngine, EngineContext parentEngineContext)
 {
     this._importEngine = importEngine;
     this._parentEngineContext = parentEngineContext;
 }
Example #14
0
 public EngineContext(ImportEngine importEngine, EngineContext parentEngineContext)
 {
     _importEngine        = importEngine;
     _parentEngineContext = parentEngineContext;
 }
Example #15
0
        public void PreviewImports_Successful_AtomicComposition_RolledBack_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value");
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 21);

            using (var atomicComposition = new AtomicComposition())
            {
                engine.PreviewImports(importer, atomicComposition);

                // Let atomicComposition get disposed thus rolledback
            }

            exportProvider.AddExport("Value", 22);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
Example #16
0
        public void SatisfyImportsOnce_Successful_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value");
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 21);

            engine.SatisfyImportsOnce(importer);

            exportProvider.AddExport("Value", 22);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
Example #17
0
        public void SatisfyImports_ZeroCollectionImport_Recomposable_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value", ImportCardinality.ZeroOrMore, true, false);
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 20);

            engine.SatisfyImports(importer);

            exportProvider.AddExport("Value", 21);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
 public PartManager(ImportEngine importEngine, ComposablePart part)
 {
     this._importEngine = importEngine;
     this._part = part;
 }
Example #19
0
        public void SatisfyImports_MissingOptionalImport_NonRecomposable_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value", ImportCardinality.ZeroOrOne, false, false);
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 20);

            engine.SatisfyImports(importer);

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.AddExport("Value", 21));

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.RemoveExport("Value"));

            GC.KeepAlive(importer);
        }
Example #20
0
        public void PreviewImports_ReleaseImports_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value");
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 21);

            engine.PreviewImports(importer, null);

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.AddExport("Value", 22));

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.RemoveExport("Value"));

            engine.ReleaseImports(importer, null);

            exportProvider.AddExport("Value", 22);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
Example #21
0
        public void SatisifyImportsOnce_Recomposable_ValueShouldNotChange_NoRecompositionRequested_ViaNonArgumentSignature()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            exportProvider.AddExport("Value", 21);

            var import = ImportDefinitionFactory.Create("Value", true);
            var importer = PartFactory.CreateImporter(import);

            engine.SatisfyImportsOnce(importer);

            Assert.AreEqual(21, importer.GetImport(import));

            exportProvider.ReplaceExportValue("Value", 42);

            Assert.AreEqual(21, importer.GetImport(import), "Value should not change!");

            GC.KeepAlive(importer);
        }
Example #22
0
        public void PreviewImports_ZeroCollectionImport_ShouldSucceed()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value", ImportCardinality.ZeroOrMore);
            var importer = PartFactory.CreateImporter(import);

            engine.PreviewImports(importer, null);

            GC.KeepAlive(importer);
        }
Example #23
0
        public void PreviewImports_MissingOptionalImport_NonRecomposable_ShouldNotBlockChanges()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value", ImportCardinality.ZeroOrOne, false, false);
            var importer = PartFactory.CreateImporter(import);

            engine.PreviewImports(importer, null);

            exportProvider.AddExport("Value", 21);
            exportProvider.AddExport("Value", 22);
            exportProvider.RemoveExport("Value");

            GC.KeepAlive(importer);
        }
Example #24
0
        public void SatisfyImports_NonRecomposable_ValueShouldNotChange()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            exportProvider.AddExport("Value", 21);

            var import = ImportDefinitionFactory.Create("Value", false);
            var importer = PartFactory.CreateImporter(import);

            engine.SatisfyImports(importer);

            Assert.AreEqual(21, importer.GetImport(import));

            // After rejection batch failures throw ChangeRejectedException to indicate that
            // the failure did not affect the container
            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.ReplaceExportValue("Value", 42));

            Assert.AreEqual(21, importer.GetImport(import), "Value should not change!");

            GC.KeepAlive(importer);
        }
Example #25
0
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!this._isDisposed)
                {
                    ExportProvider               rootProvider = null;
                    AggregateExportProvider      aggregatingExportProvider = null;
                    ComposablePartExportProvider partExportProvider        = null;
                    CatalogExportProvider        catalogExportProvider     = null;
                    ImportEngine importEngine = null;

                    lock (this._lock)
                    {
                        if (!this._isDisposed)
                        {
                            rootProvider       = this._rootProvider;
                            this._rootProvider = null;

                            aggregatingExportProvider       = this._aggregatingExportProvider;
                            this._aggregatingExportProvider = null;

                            partExportProvider       = this._partExportProvider;
                            this._partExportProvider = null;

                            catalogExportProvider       = this._catalogExportProvider;
                            this._catalogExportProvider = null;

                            importEngine       = this._importEngine;
                            this._importEngine = null;

                            this._isDisposed = true;
                        }
                    }

                    if (rootProvider != null)
                    {
                        rootProvider.ExportsChanged  -= this.OnExportsChangedInternal;
                        rootProvider.ExportsChanging -= this.OnExportsChangingInternal;
                    }

                    if (aggregatingExportProvider != null)
                    {
                        aggregatingExportProvider.Dispose();
                    }

                    if (catalogExportProvider != null)
                    {
                        catalogExportProvider.Dispose();
                    }

                    if (partExportProvider != null)
                    {
                        partExportProvider.Dispose();
                    }

                    if (importEngine != null)
                    {
                        importEngine.Dispose();
                    }
                }
            }
        }
Example #26
0
        public void SatisfyImports_NonRecomposable_Prerequisite_ValueShouldNotChange()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import = ImportDefinitionFactory.Create("Value", false, true);
            var importer = PartFactory.CreateImporter(import);

            exportProvider.AddExport("Value", 21);

            engine.SatisfyImports(importer);

            Assert.AreEqual(21, importer.GetImport(import));

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.ReplaceExportValue("Value", 42));

            Assert.AreEqual(21, importer.GetImport(import), "Value should NOT change!");

            GC.KeepAlive(importer);
        }
Example #27
0
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_isDisposed)
                {
                    ExportProvider rootProvider = null;
                    IDisposable    disposableAncestorExportProvider    = null;
                    IDisposable    disposableLocalExportProvider       = null;
                    IDisposable    disposableRootProvider              = null;
                    ComposablePartExportProvider partExportProvider    = null;
                    CatalogExportProvider        catalogExportProvider = null;
                    ImportEngine importEngine = null;

                    lock (_lock)
                    {
                        if (!_isDisposed)
                        {
                            rootProvider  = _rootProvider;
                            _rootProvider = null;

                            disposableRootProvider  = _disposableRootProvider;
                            _disposableRootProvider = null;

                            disposableLocalExportProvider  = _disposableLocalExportProvider;
                            _disposableLocalExportProvider = null;
                            _localExportProvider           = null;

                            disposableAncestorExportProvider  = _disposableAncestorExportProvider;
                            _disposableAncestorExportProvider = null;
                            _ancestorExportProvider           = null;

                            partExportProvider  = _partExportProvider;
                            _partExportProvider = null;

                            catalogExportProvider  = _catalogExportProvider;
                            _catalogExportProvider = null;

                            importEngine  = _importEngine;
                            _importEngine = null;

                            _isDisposed = true;
                        }
                    }

                    if (rootProvider != null)
                    {
                        rootProvider.ExportsChanged  -= OnExportsChangedInternal;
                        rootProvider.ExportsChanging -= OnExportsChangingInternal;
                    }

                    if (disposableRootProvider != null)
                    {
                        disposableRootProvider.Dispose();
                    }

                    if (disposableAncestorExportProvider != null)
                    {
                        disposableAncestorExportProvider.Dispose();
                    }

                    if (disposableLocalExportProvider != null)
                    {
                        disposableLocalExportProvider.Dispose();
                    }

                    if (catalogExportProvider != null)
                    {
                        catalogExportProvider.Dispose();
                    }

                    if (partExportProvider != null)
                    {
                        partExportProvider.Dispose();
                    }

                    if (importEngine != null)
                    {
                        importEngine.Dispose();
                    }
                }
            }
        }
Example #28
0
        public void SatisfyImports_OneRecomposable_OneNotRecomposable()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import1 = ImportDefinitionFactory.Create("Value", true);
            var import2 = ImportDefinitionFactory.Create("Value", false);
            var importer = PartFactory.CreateImporter(import1, import2);

            exportProvider.AddExport("Value", 21);

            engine.SatisfyImports(importer);

            // Initial compose values should be 21
            Assert.AreEqual(21, importer.GetImport(import1));
            Assert.AreEqual(21, importer.GetImport(import2));

            // Reset value to ensure it doesn't get set to same value again
            importer.ResetImport(import1);
            importer.ResetImport(import2);

            ExceptionAssert.Throws<ChangeRejectedException>(() =>
                exportProvider.ReplaceExportValue("Value", 42));

            Assert.AreEqual(null, importer.GetImport(import1), "Value should NOT have been set!");
            Assert.AreEqual(null, importer.GetImport(import2), "Value should NOT have been set!");

            GC.KeepAlive(importer);
        }
        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!_isDisposed)
                {
                    //Note:  We do not dispose _lock on dispose because DisposePart needs it to check isDisposed state
                    //          to eliminate race conditions between it and Dispose
                    INotifyComposablePartCatalogChanged catalogToUnsubscribeFrom = null;
                    HashSet <IDisposable>   partsToDispose          = null;
                    ImportEngine            importEngine            = null;
                    ExportProvider          sourceProvider          = null;
                    AggregateExportProvider aggregateExportProvider = null;
                    try
                    {
                        using (_lock.LockStateForWrite())
                        {
                            if (!_isDisposed)
                            {
                                catalogToUnsubscribeFrom = _catalog as INotifyComposablePartCatalogChanged;
                                _catalog = null;

                                aggregateExportProvider = _innerExportProvider as AggregateExportProvider;
                                _innerExportProvider    = null;

                                sourceProvider  = _sourceProvider;
                                _sourceProvider = null;

                                importEngine  = _importEngine;
                                _importEngine = null;

                                partsToDispose = _partsToDispose;
                                _gcRoots       = null;
                                _isDisposed    = true;
                            }
                        }
                    }
                    finally
                    {
                        if (catalogToUnsubscribeFrom != null)
                        {
                            catalogToUnsubscribeFrom.Changing -= OnCatalogChanging;
                        }

                        if (aggregateExportProvider != null)
                        {
                            aggregateExportProvider.Dispose();
                        }

                        if (sourceProvider != null)
                        {
                            sourceProvider.ExportsChanging -= OnExportsChangingInternal;
                        }

                        if (importEngine != null)
                        {
                            importEngine.Dispose();
                        }

                        if (partsToDispose != null)
                        {
                            foreach (var part in partsToDispose)
                            {
                                part.Dispose();
                            }
                        }
                    }
                }
            }
        }
Example #30
0
        public void SatisfyImports_TwoRecomposables_SingleExportValueChanged()
        {
            var exportProvider = ExportProviderFactory.CreateRecomposable();
            var engine = new ImportEngine(exportProvider);

            var import1 = ImportDefinitionFactory.Create("Value1", true);
            var import2 = ImportDefinitionFactory.Create("Value2", true);
            var importer = PartFactory.CreateImporter(import1, import2);

            exportProvider.AddExport("Value1", 21);
            exportProvider.AddExport("Value2", 23);

            engine.SatisfyImports(importer);

            Assert.AreEqual(21, importer.GetImport(import1));
            Assert.AreEqual(23, importer.GetImport(import2));

            importer.ResetImport(import1);
            importer.ResetImport(import2);

            // Only change Value1 
            exportProvider.ReplaceExportValue("Value1", 42);

            Assert.AreEqual(42, importer.GetImport(import1), "Value should have been set!");

            Assert.AreEqual(null, importer.GetImport(import2), "Value should NOT have changed to the value in the container.");

            GC.KeepAlive(importer);
        }
        private void DisposePart(object exportedValue, CatalogPart catalogPart, AtomicComposition atomicComposition)
        {
            Assumes.NotNull(catalogPart);

            if (_isDisposed)
            {
                return;
            }

            ImportEngine importEngine = null;

            using (_lock.LockStateForWrite())
            {
                if (_isDisposed)
                {
                    return;
                }

                importEngine = _importEngine;
            }
            if (importEngine != null)
            {
                importEngine.ReleaseImports(catalogPart.Part, atomicComposition);
            }
            if (exportedValue != null)
            {
                atomicComposition.AddCompleteActionAllowNull(() =>
                {
                    AllowPartCollection(exportedValue);
                });
            }

            IDisposable diposablePart = catalogPart.Part as IDisposable;

            if (diposablePart != null)
            {
                atomicComposition.AddCompleteActionAllowNull(() =>
                {
                    bool removed = false;

                    if (_isDisposed)
                    {
                        return;
                    }
                    using (_lock.LockStateForWrite())
                    {
                        if (_isDisposed)
                        {
                            return;
                        }

                        removed = _partsToDispose.Remove(diposablePart);
                    }

                    if (removed)
                    {
                        diposablePart.Dispose();
                    }
                });
            }
        }
 public EngineContext(ImportEngine importEngine, EngineContext parentEngineContext)
 {
     this._importEngine        = importEngine;
     this._parentEngineContext = parentEngineContext;
 }