public void Constructor2_ArrayAsProvidersArgument_ShouldNotAllowModificationAfterConstruction() { var providers = new ExportProvider[] { ExportProviderFactory.Create() }; var provider = new AggregateExportProvider((IEnumerable<ExportProvider>)providers); providers[0] = null; Assert.IsNotNull(provider.Providers[0]); }
/// <summary> /// Initializes a new instance of the <see cref="CompositionContainer"/> class /// with the specified catalog and export providers. /// </summary> /// <param name="compositionSettings"> /// <see cref="CompositionOptions"/> enumeration with flags controlling the composition. /// </param> /// <param name="providers"> /// A <see cref="Array"/> of <see cref="ExportProvider"/> objects which provide /// the <see cref="CompositionContainer"/> access to <see cref="Export"/> objects, /// or <see langword="null"/> to set <see cref="Providers"/> to an empty /// <see cref="ReadOnlyCollection{T}"/>. /// </param> /// <exception cref="ArgumentException"> /// <paramref name="providers"/> contains an element that is <see langword="null"/>. /// </exception> public CompositionContainer(ComposablePartCatalog catalog, CompositionOptions compositionOptions, params ExportProvider[] providers) { if (compositionOptions > (CompositionOptions.DisableSilentRejection | CompositionOptions.IsThreadSafe | CompositionOptions.ExportCompositionService)) { throw new ArgumentOutOfRangeException("compositionOptions"); } this._compositionOptions = compositionOptions; this._partExportProvider = new ComposablePartExportProvider(compositionOptions); this._partExportProvider.SourceProvider = this; bool multiProvider = (catalog != null) || providers.Length > 0; if (multiProvider) { if (catalog != null) { this._catalogExportProvider = new CatalogExportProvider(catalog, compositionOptions); this._catalogExportProvider.SourceProvider = this; this._localExportProvider = new AggregateExportProvider(this._partExportProvider, this._catalogExportProvider); } else { this._localExportProvider = new AggregateExportProvider(this._partExportProvider); } if (providers != null && providers.Length > 0) { this._ancestorExportProvider = new AggregateExportProvider(providers); this._rootProvider = new AggregateExportProvider(this._localExportProvider, this._ancestorExportProvider); } else { this._rootProvider = this._localExportProvider; } } else { this._rootProvider = this._partExportProvider; } //Insert Composition Service if (compositionOptions.HasFlag(CompositionOptions.ExportCompositionService)) { this.ComposeExportedValue <ICompositionService>(new CompositionServiceShim(this)); } this._rootProvider.ExportsChanged += this.OnExportsChangedInternal; this._rootProvider.ExportsChanging += this.OnExportsChangingInternal; this._providers = (providers != null) ? new ReadOnlyCollection <ExportProvider>((ExportProvider[])providers.Clone()) : EmptyProviders; }
public CompositionContainer(ComposablePartCatalog catalog, bool isThreadSafe, params ExportProvider[] providers) { this._isThreadSafe = isThreadSafe; this._partExportProvider = new ComposablePartExportProvider(isThreadSafe); this._partExportProvider.SourceProvider = this; // the count of all aggregrated providers = 1 (Part EP) + 1 (Catalog EP, if present) + count of given providers; int reservedProvidersLength = 1 + ((catalog != null) ? 1 : 0); int aggregatedProvidersLength = reservedProvidersLength + ((providers != null) ? providers.Length : 0); if (aggregatedProvidersLength > 1) { ExportProvider[] aggregatedProviders = new ExportProvider[aggregatedProvidersLength]; // Add the parts provider aggregatedProviders[0] = this._partExportProvider; // Add the catalog provider if (catalog != null) { this._catalogExportProvider = new CatalogExportProvider(catalog, isThreadSafe); this._catalogExportProvider.SourceProvider = this; aggregatedProviders[1] = this._catalogExportProvider; } // Add the rest of providers if ((providers != null) && (providers.Length > 0)) { Array.Copy(providers, 0, aggregatedProviders, reservedProvidersLength, providers.Length); } // Create the aggregating provider and if any of the aggregatedProviders is null the constructor will throw an ArgumentExeption this._aggregatingExportProvider = new AggregateExportProvider(aggregatedProviders); this._rootProvider = this._aggregatingExportProvider; } else { Assumes.IsTrue(aggregatedProvidersLength == 1); this._rootProvider = this._partExportProvider; } this._rootProvider.ExportsChanged += this.OnExportsChangedInternal; this._rootProvider.ExportsChanging += this.OnExportsChangingInternal; this._providers = (providers != null) ? new ReadOnlyCollection <ExportProvider>((ExportProvider[])providers.Clone()) : EmptyProviders; }
public void CanBeCollectedAfterDispose() { AggregateExportProvider exportProvider = new AggregateExportProvider(); var catalog = new AggregateCatalog(CatalogFactory.CreateDefaultAttributed()); var container = new CompositionContainer(catalog, exportProvider); WeakReference weakContainer = new WeakReference(container); container.Dispose(); container = null; GC.Collect(); GC.WaitForPendingFinalizers(); Assert.IsFalse(weakContainer.IsAlive); GC.KeepAlive(exportProvider); GC.KeepAlive(catalog); }
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; }
/// <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(); } } } } } }
/// <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(); } } } }
public void Constructor2_EmptyEnumerableAsProvidersArgument_ShouldSetProvidersPropertyToEmpty() { var provider = new AggregateExportProvider(Enumerable.Empty<ExportProvider>()); EnumerableAssert.IsEmpty(provider.Providers); }
public void Constructor2_EmptyArrayAsProvidersArgument_ShouldSetProvidersPropertyToEmpty() { var provider = new AggregateExportProvider((IEnumerable<ExportProvider>)new ExportProvider[0]); EnumerableAssert.IsEmpty(provider.Providers); }
public void Constructor1_NullAsProvidersArgument_ShouldSetProvidersPropertyToEmpty() { var provider = new AggregateExportProvider((ExportProvider[])null); EnumerableAssert.IsEmpty(provider.Providers); }
/// <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; AggregateExportProvider aggregateExportProvider = null; try { using (this._lock.LockStateForWrite()) { if (!this._isDisposed) { catalogToUnsubscribeFrom = this._catalog as INotifyComposablePartCatalogChanged; this._catalog = null; aggregateExportProvider = this._innerExportProvider as AggregateExportProvider; this._innerExportProvider = 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 (aggregateExportProvider != null) { aggregateExportProvider.Dispose(); } 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(); } } } } }