| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273 |
- // -----------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // -----------------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Factories;
- using System.ComponentModel.Composition.Hosting;
- using System.ComponentModel.Composition.UnitTesting;
- using System.Linq;
- using System.Reflection;
- using System.UnitTesting;
- using Microsoft.VisualStudio.TestTools.UnitTesting;
- namespace Tests.Integration
- {
- [TestClass]
- public class LifetimeTests
- {
- [Export]
- public class AnyPartSimple
- {
- }
- [Export]
- public class AnyPartDisposable : IDisposable
- {
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [Export]
- public class AnyPartRecomposable
- {
- [Import("Value", AllowRecomposition = true)]
- public int Value { get; set; }
- }
- [Export]
- public class AnyPartDisposableRecomposable : IDisposable
- {
- [Import("Value", AllowRecomposition = true)]
- public int Value { get; set; }
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [TestMethod]
- public void PartAddedViaAddExportedValue_ShouldNotBeDisposedWithContainer()
- {
- var container = new CompositionContainer();
- var disposablePart = new AnyPartDisposable();
- var batch = new CompositionBatch();
- batch.AddPart(batch);
- container.Compose(batch);
- container.Dispose();
- Assert.IsFalse(disposablePart.IsDisposed);
- }
- [TestMethod]
- public void PartAddedTwice_AppearsTwice()
- {
- // You probably shouldn't be adding a part to the container twice, but it's not something we're going to check for and throw an exception on
- var container = new CompositionContainer();
- var disposable = new AnyPartDisposable();
- var part = AttributedModelServices.CreatePart(disposable);
- var batch = new CompositionBatch();
- batch.AddPart(part);
- container.Compose(batch);
- batch = new CompositionBatch();
- batch.AddPart(part);
- container.Compose(batch);
- var exports = container.GetExports<AnyPartDisposable>();
- Assert.AreEqual(2, exports.Count());
- container.Dispose();
- }
- [TestMethod]
- public void AnyPart_Simple_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(AnyPartSimple));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<AnyPartSimple>());
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void AnyPart_Disposable_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(AnyPartDisposable));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<AnyPartDisposable>());
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void AnyPart_Disposable_ShouldBeDisposedWithContainer()
- {
- var catalog = new TypeCatalog(typeof(AnyPartDisposable));
- var container = new CompositionContainer(catalog);
- var exportedValue = container.GetExportedValue<AnyPartDisposable>();
- Assert.IsFalse(exportedValue.IsDisposed);
- container.Dispose();
- Assert.IsTrue(exportedValue.IsDisposed, "AnyPart should be disposed with the container!");
- }
- [TestMethod]
- public void AnyPart_RecomposabeImport_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(AnyPartRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<AnyPartRecomposable>());
- refTracker.CollectAndAssert();
- // Lets make sure recomposition doesn't blow anything up here.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- var exportedValue = (AnyPartRecomposable)refTracker.ReferencesNotExpectedToBeCollected[0].Target;
- Assert.AreEqual(42, exportedValue.Value);
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void AnyPart_DisposableRecomposabeImport_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(AnyPartDisposableRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<AnyPartDisposableRecomposable>());
- refTracker.CollectAndAssert();
- // Lets make sure recomposition doesn't blow anything up here.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- var exportedValue = (AnyPartDisposableRecomposable)refTracker.ReferencesNotExpectedToBeCollected[0].Target;
- Assert.AreEqual(42, exportedValue.Value);
- GC.KeepAlive(container);
- container.Dispose();
- Assert.IsTrue(exportedValue.IsDisposed, "Any parts should be disposed with the container!");
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.Shared)]
- public class SharedPartSimple
- {
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.Shared)]
- public class SharedPartDisposable : IDisposable
- {
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.Shared)]
- public class SharedPartRecomposable
- {
- [Import("Value", AllowRecomposition = true)]
- public int Value { get; set; }
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.Shared)]
- public class SharedPartDisposableRecomposable : IDisposable
- {
- [Import("Value", AllowRecomposition = true)]
- public int Value { get; set; }
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [TestMethod]
- public void SharedPart_Simple_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(SharedPartSimple));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<SharedPartSimple>());
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void SharedPart_Disposable_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(SharedPartDisposable));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<SharedPartDisposable>());
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void SharedPart_Disposable_ShouldBeDisposedWithContainer()
- {
- var catalog = new TypeCatalog(typeof(SharedPartDisposable));
- var container = new CompositionContainer(catalog);
- var export = container.GetExportedValue<SharedPartDisposable>();
- Assert.IsFalse(export.IsDisposed);
- container.Dispose();
- Assert.IsTrue(export.IsDisposed, "SharedPart should be disposed with the container!");
- }
-
- [TestMethod]
- public void SharedPart_RecomposabeImport_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(SharedPartRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<SharedPartRecomposable>());
- refTracker.CollectAndAssert();
- // Lets make sure recomposition doesn't blow anything up here.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- var exportedValue = (SharedPartRecomposable)refTracker.ReferencesNotExpectedToBeCollected[0].Target;
- Assert.AreEqual(42, exportedValue.Value);
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void SharedPart_DisposableRecomposabeImport_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(SharedPartDisposableRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<SharedPartDisposableRecomposable>());
- refTracker.CollectAndAssert();
- // Lets make sure recomposition doesn't blow anything up here.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- var exportedValue = (SharedPartDisposableRecomposable)refTracker.ReferencesNotExpectedToBeCollected[0].Target;
- Assert.AreEqual(42, exportedValue.Value);
- container.Dispose();
- Assert.IsTrue(exportedValue.IsDisposed, "Any parts should be disposed with the container!");
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedPartSimple
- {
-
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedPartRecomposable
- {
- [Import("Value", AllowRecomposition = true)]
- public int Value { get; set; }
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedPartDisposable : IDisposable
- {
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedPartDisposableRecomposable : IDisposable
- {
- private int _value;
- [Import("Value", AllowRecomposition = true)]
- public int Value
- {
- get
- {
- if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().Name);
- return this._value;
- }
- set
- {
- if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().Name);
- this._value = value;
- }
- }
- public bool IsDisposed { get; set; }
- public void Dispose()
- {
- Assert.IsFalse(IsDisposed);
- IsDisposed = true;
- }
- }
- [TestMethod]
- public void NonSharedPart_Disposable_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartDisposable));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<NonSharedPartDisposable>());
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void NonSharedPart_Disposable_ShouldBeDisposedWithContainer()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartDisposable));
- var container = new CompositionContainer(catalog);
- var export = container.GetExportedValue<NonSharedPartDisposable>();
- Assert.IsFalse(export.IsDisposed);
- container.Dispose();
- Assert.IsTrue(export.IsDisposed, "NonSharedParts should be disposed with the container!");
- }
- [TestMethod]
- public void NonSharedPart_RecomposableImport_WithReference_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var exportedValue = container.GetExportedValue<NonSharedPartRecomposable>();
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(exportedValue);
- refTracker.CollectAndAssert();
- // Recompose should work because we are still holding a reference to the exported value.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- Assert.AreEqual(42, exportedValue.Value, "Value should have been recomposed");
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void NonSharedPart_DisposableRecomposabeImport_NoReference_ShouldNotBeCollected()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartDisposableRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesNotExpectedToBeCollected(
- container.GetExportedValue<NonSharedPartDisposableRecomposable>());
- refTracker.CollectAndAssert();
- // Recompose just to ensure we don't blow up, even though we don't expect anything to happen.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- var exportedValue = (NonSharedPartDisposableRecomposable)refTracker.ReferencesNotExpectedToBeCollected[0].Target;
- Assert.AreEqual(42, exportedValue.Value, "Value shoudl ahve been recomposed.");
-
- GC.KeepAlive(container);
- }
- [Export]
- public class SharedState
- {
- public static int instanceNumber = 0;
- public SharedState()
- {
- MyInstanceNumber = instanceNumber++;
- }
- public int MyInstanceNumber { get; private set; }
- }
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedState
- {
- [Import(AllowRecomposition = true)]
- public SharedState State { set { ExportState = value; } }
- [Export("SharedFromNonShared")]
- public SharedState ExportState { get; private set; }
- }
- [TestMethod]
- public void NonSharedPart_TwoRecomposablePartsSameExportedValue()
- {
- // This test is primarily used to ensure that we allow for multiple parts to be associated
- // with the same exported value.
- var catalog = new TypeCatalog(typeof(SharedState), typeof(NonSharedState));
- var container = new CompositionContainer(catalog);
- var export1 = container.GetExportedValue<SharedState>("SharedFromNonShared");
- var export2 = container.GetExportedValue<SharedState>("SharedFromNonShared");
- // Same exported value that comes from two different recomposable part instances.
- Assert.AreEqual(export1.MyInstanceNumber, export2.MyInstanceNumber, "Should be the same shared object!");
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class SharedImporter
- {
- [Import(RequiredCreationPolicy = CreationPolicy.Shared)]
- public AnyPartSimple AnyPartSimple { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.Shared)]
- public AnyPartDisposable AnyPartDisposable { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.Shared)]
- public AnyPartRecomposable AnyPartRecomposable { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.Shared)]
- public AnyPartDisposableRecomposable AnyPartDisposableRecomposable { get; set; }
- }
- [Export]
- [PartCreationPolicy(CreationPolicy.NonShared)]
- public class NonSharedImporter
- {
- [Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
- public AnyPartSimple AnyPartSimple { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
- public AnyPartDisposable AnyPartDisposable { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
- public AnyPartRecomposable AnyPartRecomposable { get; set; }
- [Import(RequiredCreationPolicy = CreationPolicy.NonShared)]
- public AnyPartDisposableRecomposable AnyPartDisposableRecomposable { get; set; }
- }
- private static CompositionContainer GetContainer()
- {
- var container = ContainerFactory.CreateWithAttributedCatalog(
- typeof(LifetimeTests).GetNestedTypes(BindingFlags.Public));
- CompositionBatch batch = new CompositionBatch();
- batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- return container;
- }
- [TestMethod]
- public void GetReleaseExport_SharedRoot_ShouldNotDisposeChain()
- {
- var container = GetContainer();
- var export = container.GetExport<SharedImporter, IDictionary<string, object>>();
- var exportedValue = export.Value;
- container.ReleaseExport(export);
- Assert.IsFalse(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsFalse(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void AddRemovePart_SharedRoot_ShouldNotDisposeChain()
- {
- var container = GetContainer();
- var exportedValue = new SharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- container.Compose(batch);
- batch = new CompositionBatch();
- batch.RemovePart(part);
- container.Compose(batch);
- Assert.IsFalse(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsFalse(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void ContainerDispose_SharedRoot_ShouldDisposeChain()
- {
- var container = GetContainer();
- var export = container.GetExport<SharedImporter>();
- var exportedValue = export.Value;
- container.Dispose();
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void GetReleaseExport_NonSharedRoot_ShouldDisposeChain()
- {
- var container = GetContainer();
- var exports = new List<Lazy<NonSharedImporter>>();
- var exportedValues = new List<NonSharedImporter>();
- // Executing this 100 times to help uncover any GC bugs
- for (int i = 0; i < 100; i++)
- {
- var export = container.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- exports.Add(export);
- exportedValues.Add(exportedValue);
- }
- for (int i = 0; i < 100; i++)
- {
- var export = exports[i];
- var exportedValue = exportedValues[i];
- container.ReleaseExport(export);
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- }
- public void GetReleaseExport_NonSharedRoot_ShouldDisposeChain_WithMetadata()
- {
- var container = GetContainer();
- var exports = new List<Lazy<NonSharedImporter, IDictionary<string, object>>>();
- var exportedValues = new List<NonSharedImporter>();
- // Executing this 100 times to help uncover any GC bugs
- for (int i = 0; i < 100; i++)
- {
- var export = container.GetExport<NonSharedImporter, IDictionary<string, object>>();
- var exportedValue = export.Value;
- exports.Add(export);
- exportedValues.Add(exportedValue);
- }
- for (int i = 0; i < 100; i++)
- {
- var export = exports[i];
- var exportedValue = exportedValues[i];
- container.ReleaseExport(export);
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- }
- [TestMethod]
- public void ReleaseExports_ShouldDispose_NonSharedParts()
- {
- var container = GetContainer();
- var export1 = container.GetExport<NonSharedImporter>();
- var exportedValue1 = export1.Value;
- var export2 = container.GetExport<NonSharedImporter>();
- var exportedValue2 = export2.Value;
- container.ReleaseExports(new[] { export1, export2 });
- Assert.IsTrue(exportedValue1.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue1.AnyPartDisposableRecomposable.IsDisposed);
- Assert.IsTrue(exportedValue2.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue2.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void AddRemovePart_NonSharedRoot_ShouldDisposeChain()
- {
- var container = GetContainer();
- var exportedValue = new NonSharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- container.Compose(batch);
- batch = new CompositionBatch();
- batch.RemovePart(part);
- container.Compose(batch);
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void ContainerDispose_NonSharedRoot_ShouldNotDisposeChain()
- {
- var container = GetContainer();
- var export = container.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- container.Dispose();
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void GetReleaseExport_NonSharedPart_ShouldNotRecomposeAfterRelease()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
-
- var export = container.GetExport<NonSharedPartRecomposable>();
- var exportedValue = export.Value;
- Assert.AreEqual(21, exportedValue.Value);
- container.ReleaseExport(export);
- // Recompose just to ensure we don't blow up, even though we don't expect anything to happen.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- Assert.AreEqual(21, exportedValue.Value, "Value should not be recomposed after ReleaseExport is called on it.");
- }
- [TestMethod]
- public void GetExportManualDisposeThenRecompose_NonSharedDisposableRecomposablePart_ShouldThrowComposition()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartDisposableRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
-
- var export = container.GetExport<NonSharedPartDisposableRecomposable>();
- var exportedValue = export.Value;
- Assert.AreEqual(21, exportedValue.Value);
- exportedValue.Dispose();
- // Recompose should cause a ObjectDisposedException.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- CompositionAssert.ThrowsError(
- ErrorId.ImportEngine_PartCannotActivate, // Cannot activate part because
- ErrorId.ReflectionModel_ImportThrewException, // Import threw an exception
- RetryMode.DoNotRetry,
- () =>
- {
- container.Compose(batch);
- });
- }
-
- [Export]
- public class MyImporter
- {
- [Import(AllowDefault = true, AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.NonShared)]
- public AnyPartDisposable AnyPartDisposable { get; set; }
- }
- [TestMethod]
- public void RecomposeCausesOldImportedValuesToBeDisposed()
- {
- var cat = new AggregateCatalog();
- var cat1 = new TypeCatalog(typeof(AnyPartDisposable));
- cat.Catalogs.Add(new TypeCatalog(typeof (MyImporter)));
- cat.Catalogs.Add(cat1);
- var container = new CompositionContainer(cat);
- var importer = container.GetExportedValue<MyImporter>();
- var anyPart = importer.AnyPartDisposable;
- Assert.IsFalse(anyPart.IsDisposed);
- Assert.IsInstanceOfType(anyPart, typeof(AnyPartDisposable));
- // Remove the instance of MyClass1
- cat.Catalogs.Remove(cat1);
- Assert.IsNull(importer.AnyPartDisposable);
- Assert.IsTrue(anyPart.IsDisposed);
- }
- private static CompositionContainer CreateParentChildContainerWithNonSharedImporter()
- {
- var parentCat = CatalogFactory.CreateAttributed(typeof(AnyPartDisposable),
- typeof(AnyPartDisposableRecomposable),
- typeof(AnyPartRecomposable),
- typeof(AnyPartSimple));
- var parent = new CompositionContainer(parentCat);
- CompositionBatch batch = new CompositionBatch();
- batch.AddExportedValue("Value", 21);
- parent.Compose(batch);
- var childCat = CatalogFactory.CreateAttributed(typeof(NonSharedImporter));
- var child = new CompositionContainer(childCat, parent);
- return child;
- }
- [TestMethod]
- public void ChildContainerGetReleaseExport_NonSharedRoot_ShouldDisposeChain()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var export = child.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- child.ReleaseExport(export);
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void ChildContainerAddRemovePart_NonSharedRoot_ShouldDisposeChain()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var exportedValue = new NonSharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- child.Compose(batch);
- batch = new CompositionBatch();
- batch.RemovePart(part);
- child.Compose(batch);
- Assert.IsTrue(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- [TestMethod]
- public void ChildContainerAddRemovePart_NonSharedRoot_ShouldNotDisposeChain()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var exportedValue = child.GetExportedValue<NonSharedImporter>();
- child.Dispose();
- Assert.IsFalse(exportedValue.AnyPartDisposable.IsDisposed);
- Assert.IsFalse(exportedValue.AnyPartDisposableRecomposable.IsDisposed);
- }
- #if CLR40
- [TestMethod]
- public void NonSharedPart_Simple_ShouldBeCollected()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartSimple));
- var container = new CompositionContainer(catalog);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- container.GetExportedValue<NonSharedPartSimple>());
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void ContainerDispose_SharedPart_ShouldCollectWholeObjectChain()
- {
- // Test only works properly with while using the real ConditionalWeakTable
- var container = GetContainer();
- var export = container.GetExport<SharedImporter>();
- var exportedValue = export.Value;
- container.Dispose();
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void AddRemovePart_SharedPart_ShouldCollectOnlyRoot()
- {
- var container = GetContainer();
-
- var exportedValue = new SharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- container.Compose(batch);
- batch = null;
- batch = new CompositionBatch();
- batch.RemovePart(part);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue);
- refTracker.AddReferencesNotExpectedToBeCollected(
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- part = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void AddRemovePart_NonSharedPart_ShouldCollectWholeObjectChain()
- {
- var container = GetContainer();
- var exportedValue = new NonSharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- container.Compose(batch);
- batch = null;
- batch = new CompositionBatch();
- batch.RemovePart(part);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- part = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void ContainerDispose_NonSharedPart_ShouldCollectWholeObjectChain()
- {
- // Test only works properly with while using the real ConditionalWeakTable
- var container = GetContainer();
- var export = container.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- container.Dispose();
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void NonSharedImporter_ReleaseReference_ShouldCollectWholeChain()
- {
- var container = GetContainer();
- var export = container.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- var refTracker = new ReferenceTracker();
- // Non-Disposable references in the chain should be GC'ed
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- // Disposable references in the chain should NOT be GC'ed
- refTracker.AddReferencesNotExpectedToBeCollected(
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void ChildContainerDispose_NonSharedPart_ShouldOnlyCleanupChildAndSimpleNonShared()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var exportedValue = child.GetExportedValue<NonSharedImporter>();
- child.Dispose();
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue, // object in child
- exportedValue.AnyPartSimple, // No reference parent so collected.
- exportedValue.AnyPartRecomposable);
- // These are in the parent and will not be cleaned out
- refTracker.AddReferencesNotExpectedToBeCollected(
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable);
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(child);
- }
- [TestMethod]
- public void ChildContainerGetReleaseExport_NonSharedPart_ShouldCollectWholeObjectChain()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var export = child.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- child.ReleaseExport(export);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(child);
- }
- [TestMethod]
- public void NonSharedPart_RecomposableImport_NoReference_ShouldBeCollected()
- {
- var catalog = new TypeCatalog(typeof(NonSharedPartRecomposable));
- var container = new CompositionContainer(catalog);
- // Setup dependency
- CompositionBatch batch = new CompositionBatch();
- var valueKey = batch.AddExportedValue("Value", 21);
- container.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- container.GetExportedValue<NonSharedPartRecomposable>());
- refTracker.CollectAndAssert();
- // Recompose just to ensure we don't blow up, even though we don't expect anything to happen.
- batch = new CompositionBatch();
- batch.RemovePart(valueKey);
- batch.AddExportedValue("Value", 42);
- container.Compose(batch);
- batch = null;
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void ChildContainerAddRemovePart_NonSharedPart_ShouldCollectWholeObjectChain()
- {
- var child = CreateParentChildContainerWithNonSharedImporter();
- var exportedValue = new NonSharedImporter();
- CompositionBatch batch = new CompositionBatch();
- var part = batch.AddPart(exportedValue);
- child.Compose(batch);
- batch = null;
- batch = new CompositionBatch();
- batch.RemovePart(part);
- child.Compose(batch);
- batch = null;
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- part = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(child);
- }
- [TestMethod]
- public void GetReleaseExport_SharedPart_ShouldCollectOnlyRoot()
- {
- var container = GetContainer();
- var export = container.GetExport<SharedImporter>();
- var exportedValue = export.Value;
- container.ReleaseExport(export);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue);
- refTracker.AddReferencesNotExpectedToBeCollected(
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void GetReleaseExport_NonSharedPart_ShouldCollectWholeObjectChain()
- {
- var container = GetContainer();
- var export = container.GetExport<NonSharedImporter>();
- var exportedValue = export.Value;
- container.ReleaseExport(export);
- var refTracker = new ReferenceTracker();
- refTracker.AddReferencesExpectedToBeCollected(
- exportedValue,
- exportedValue.AnyPartDisposable,
- exportedValue.AnyPartDisposableRecomposable,
- exportedValue.AnyPartRecomposable,
- exportedValue.AnyPartSimple);
- export = null;
- exportedValue = null;
- refTracker.CollectAndAssert();
- GC.KeepAlive(container);
- }
- [TestMethod]
- public void ReleaseExports_ShouldWorkWithExportCollection()
- {
- var container = GetContainer();
- var exports = container.GetExports<NonSharedImporter>();
- Assert.IsTrue(exports.Count() > 0);
- var exportedValues = exports.Select(export => export.Value).ToList();
- container.ReleaseExports(exports);
- foreach (var obj in exportedValues)
- {
- Assert.IsTrue(obj.AnyPartDisposable.IsDisposed);
- Assert.IsTrue(obj.AnyPartDisposableRecomposable.IsDisposed);
- }
- }
- #endif
- }
- }
|