Example #1
0
        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!");
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }
Example #12
0
        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;
            }
        }
Example #13
0
        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;
            }
        }
Example #14
0
        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();
        }
Example #16
0
        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();
        }
Example #19
0
        public void Initializable_components_are_not_tracked()
        {
            Container.Register(Component.For <ISimpleService>()
                               .ImplementedBy <SimpleServiceInitializable>()
                               .LifeStyle.Transient);

            ReferenceTracker
            .Track(() => Container.Resolve <ISimpleService>())
            .AssertNoLongerReferenced();
        }
Example #20
0
        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();
        }
Example #21
0
 private unsafe void DisposeTrackerSource()
 {
     if (ReferenceTrackerPtr != IntPtr.Zero)
     {
         if (!PreventReleaseFromTrackerSourceOnDispose)
         {
             ReferenceTracker.ReleaseFromTrackerSource(ReferenceTrackerPtr);
         }
         ReferenceTracker.IUnknownVftbl.Release(ReferenceTrackerPtr);
     }
 }
Example #22
0
 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();
        }
Example #24
0
        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();
            }
        }
Example #25
0
        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();
        }
Example #27
0
        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();
        }
Example #28
0
        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);
        }
Example #29
0
        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();
        }
Example #30
0
        /// <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();
        }