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!"); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
public static void ArrayUpdate <TSourceElement, TTargetElement>( Mapper mapper, ReferenceTracker referenceTracker, IEnumerable <TSourceElement> source, TTargetElement[] target, Func <TSourceElement, TTargetElement, bool> comparer) where TSourceElement : class where TTargetElement : class, new() { MapItems(mapper, referenceTracker, source, target, comparer); var arrayTarget = target as TTargetElement[]; var sourceCount = source.Count(); if (sourceCount > arrayTarget.Length) { arrayTarget = target = new TTargetElement[sourceCount]; } int index = 0; foreach (var item in source) { var targetItem = (TTargetElement)referenceTracker[item, typeof(TTargetElement)]; target[index++] = targetItem; } }
public static void Update <TSourceElement, TTargetElement>( Mapper mapper, ReferenceTracker referenceTracker, IEnumerable <TSourceElement> source, ICollection <TTargetElement> target, Func <TSourceElement, TTargetElement, bool> comparer) where TSourceElement : class where TTargetElement : class, new() { switch (target) { case TTargetElement[] array: ArrayUpdate(mapper, referenceTracker, source, array, comparer); break; case Queue <TTargetElement> queue: UpdateQueue(mapper, referenceTracker, source, queue, comparer); break; case Stack <TTargetElement> stack: UpdateStack(mapper, referenceTracker, source, stack, comparer); break; default: CollectionUpdate(mapper, referenceTracker, source, target, comparer); break; } }
private static void MapItems <TSourceElement, TTargetElement>(Mapper mapper, ReferenceTracker referenceTracker, IEnumerable <TSourceElement> source, IEnumerable <TTargetElement> target, Func <TSourceElement, TTargetElement, bool> comparer) where TSourceElement : class where TTargetElement : class, new() { //search items to add, map and add them foreach (var sourceItem in source) { bool addToList = true; foreach (var targetItem in target) { if (comparer(sourceItem, targetItem)) { mapper.Map(sourceItem, targetItem, referenceTracker); addToList = false; //we already updated break; //next source item } } if (addToList) { var targetItem = new TTargetElement(); mapper.Map(sourceItem, targetItem, referenceTracker); } } }
public void TransientReferencesAreNotHeldByContainer() { Kernel.Register(Component.For <EmptyClass>().LifeStyle.Transient); ReferenceTracker .Track(() => Kernel.Resolve <EmptyClass>()) .AssertNoLongerReferenced(); }
public void Factory_is_tracked_by_the_container() { Container.Register(Component.For <IDummyComponentFactory>().AsFactory()); ReferenceTracker .Track(() => Container.Resolve <IDummyComponentFactory>()) .AssertStillReferenced(); }
public void Explicitly_registered_factory_is_tracked() { Container.Register(Component.For <Func <A> >().AsFactory()); ReferenceTracker .Track(() => Container.Resolve <Func <A> >()) .AssertStillReferenced(); }
public void Managed_externally_factory_component_transient_is_not_tracked_by_the_container() { Kernel.Register(Component.For <DisposableComponent>() .LifeStyle.Transient .UsingFactoryMethod(() => new DisposableComponent(), managedExternally: true)); ReferenceTracker .Track(() => Kernel.Resolve <DisposableComponent>()) .AssertNoLongerReferenced(); }
public void Initializable_components_are_not_tracked() { Container.Register(Component.For <ISimpleService>() .ImplementedBy <SimpleServiceInitializable>() .LifeStyle.Transient); ReferenceTracker .Track(() => Container.Resolve <ISimpleService>()) .AssertNoLongerReferenced(); }
public void Typed_factory_obeys_release_policy_tracking() { Container.Register( Component.For <INonDisposableFactory>().LifeStyle.Transient.AsFactory(), Component.For <DisposableComponent>().LifeStyle.Transient); var factory = Container.Resolve <INonDisposableFactory>(); ReferenceTracker .Track(() => factory.Create()) .AssertStillReferenced(); }
private unsafe void DisposeTrackerSource() { if (ReferenceTrackerPtr != IntPtr.Zero) { if (!PreventReleaseFromTrackerSourceOnDispose) { ReferenceTracker.ReleaseFromTrackerSource(ReferenceTrackerPtr); } ReferenceTracker.IUnknownVftbl.Release(ReferenceTrackerPtr); } }
private unsafe void ResurrectTrackerSource() { if (ReferenceTrackerPtr != IntPtr.Zero) { ReferenceTracker.IUnknownVftbl.AddRef(ReferenceTrackerPtr); if (!PreventReleaseFromTrackerSourceOnDispose) { ReferenceTracker.AddRefFromTrackerSource(ReferenceTrackerPtr); } } }
public void Factory_obeys_release_policy_tracking() { Container.Register(Component.For <DisposableFoo>().LifeStyle.Transient, Component.For <UsesDisposableFooDelegate>().LifeStyle.Transient); var dependsOnFoo = Container.Resolve <UsesDisposableFooDelegate>(); ReferenceTracker .Track(() => dependsOnFoo.GetFoo()) .AssertStillReferenced(); }
public void Transient_depending_on_scoped_component_is_not_tracked_by_the_container() { Container.Register(Component.For <DisposableFoo>().LifeStyle.Scoped(), Component.For <UsesDisposableFoo>().LifeStyle.Transient); using (Container.BeginScope()) { ReferenceTracker .Track(() => Container.Resolve <UsesDisposableFoo>()) .AssertNoLongerReferenced(); } }
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); }
public void Factory_obeys_release_policy_non_tracking() { #pragma warning disable 612,618 Container.Kernel.ReleasePolicy = new NoTrackingReleasePolicy(); #pragma warning restore 612,618 Container.Register(Component.For <DisposableFoo>().LifeStyle.Transient, Component.For <UsesDisposableFooDelegate>().LifeStyle.Transient); var dependsOnFoo = Container.Resolve <UsesDisposableFooDelegate>(); ReferenceTracker .Track(() => dependsOnFoo.GetFoo()) .AssertNoLongerReferenced(); }
public void Typed_factory_lets_go_of_component_reference_on_release() { Container.Register( Component.For <IDisposableFactory>().LifeStyle.Transient.AsFactory(), Component.For <DisposableComponent>().LifeStyle.Transient); var factory = Container.Resolve <IDisposableFactory>(); var tracker = ReferenceTracker.Track(() => factory.Create()); tracker.AssertStillReferencedAndDo(component => factory.Destroy(component)); tracker.AssertNoLongerReferenced(); }
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); }
public void Component_released_via_factory_is_not_tracked() { Container.Register( Component.For <INonDisposableFactory>().LifeStyle.Transient.AsFactory(), Component.For <DisposableComponent>().LifeStyle.Transient); var factory = Container.Resolve <INonDisposableFactory>(); var tracker = ReferenceTracker.Track(() => factory.Create()); tracker.AssertStillReferencedAndDo(component => factory.LetGo(component)); tracker.AssertNoLongerReferenced(); }
/// <summary> /// Initializes a new instance of the EveCache class that uses the specified /// <see cref="ObjectCache" /> to store data. /// </summary> /// <param name="cache"> /// The <see cref="ObjectCache" /> used to store items. /// </param> public EveCache(ObjectCache cache) : base() { Contract.Requires(cache != null, Resources.Messages.EveCache_CacheCannotBeNull); this.innerCache = cache; this.innerReferenceCollection = new ReferenceTracker(); // The master lock needs recursive read locks so that region locks don't // unnecessarily block. this.masterLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); this.regionLocks = new ConcurrentDictionary <string, ReaderWriterLockSlim>(); this.statistics = new EveCacheStatistics(); }