Click here to Skip to main content
15,891,828 members
Articles / DevOps / Testing

Composite Application Reloaded

Rate me:
Please Sign up or sign in to vote.
4.88/5 (38 votes)
11 May 2011CPOL12 min read 118.1K   1.5K   95  
A much simpler composite application library.
// -----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// -----------------------------------------------------------------------
#if !CLR40
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Internal;
using Microsoft.Internal.Collections;

namespace Microsoft.Internal.Collections
{
    // This is a broken implementation of ConditionalWeakTable that allows us
    // to compile and work on versions of .Net eariler then 4.0. This class is
    // broken when there are circular dependencies between keys and values, which
    // can only be fixed by using some specific CLR 4.0 features.
    // For code samples of the broken behavior see ConditionalWeakTableTests.cs.
    internal class ConditionalWeakTable<TKey, TValue> 
        where TKey : class
        where TValue : class
    {
        private readonly Dictionary<object, TValue> _table;
        private int _capacity = 4;

        public ConditionalWeakTable()
        {
            this._table = new Dictionary<object, TValue>();
        }

        public void Add(TKey key, TValue value)
        {
            CleanupDeadReferences();
            this._table.Add(CreateWeakKey(key), value);
        }

        public bool Remove(TKey key)
        {
            return this._table.Remove(key);
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            return this._table.TryGetValue(key, out value);
        }

        private void CleanupDeadReferences()
        {
            if (this._table.Count < _capacity)
            {
                return;
            }

            object[] deadKeys = this._table.Keys
                .Where(weakRef => !((EquivalentWeakReference)weakRef).IsAlive).ToArray();

            foreach (var deadKey in deadKeys)
            {
                this._table.Remove(deadKey);
            }

            if (this._table.Count >= _capacity)
            {
                _capacity *= 2;
            }
        }

        private static object CreateWeakKey(TKey key)
        {
            return new EquivalentWeakReference(key);
        }

        private class EquivalentWeakReference
        {
            private readonly WeakReference _weakReference;
            private readonly int _hashCode;

            public EquivalentWeakReference(object obj)
            {
                this._hashCode = obj.GetHashCode();
                this._weakReference = new WeakReference(obj);
            }

            public bool IsAlive
            {
                get
                {
                    return this._weakReference.IsAlive;
                }
            }

            public override bool Equals(object obj)
            {
                EquivalentWeakReference weakRef = obj as EquivalentWeakReference;

                if (weakRef != null)
                {
                    obj = weakRef._weakReference.Target;
                }

                if (obj == null)
                {
                    return base.Equals(weakRef);
                }
                
                return object.Equals(this._weakReference.Target, obj);
            }

            public override int GetHashCode()
            {
                return this._hashCode;
            }
        }
    }
}
#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) http://www.ansibleww.com.au
Australia Australia
The Australia born French man who went back to Australia later in life...
Finally got over life long (and mostly hopeless usually, yay!) chronic sicknesses.
Worked in Sydney, Brisbane, Darwin, Billinudgel, Darwin and Melbourne.

Comments and Discussions