Click here to Skip to main content
15,893,790 members
Articles / Programming Languages / C# 4.0

Universal Type Extender

Rate me:
Please Sign up or sign in to vote.
4.83/5 (30 votes)
5 Jun 2013Ms-PL11 min read 73.5K   569   62  
Emulate extension properties by extending any reference type with any other type.
// file     : ExtensionRepository.RepositoryItem.cs
// project  : UniversalTypeExtender
// author   : Thorsten Bruning
// date     : 10.09.2011

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace TB.ComponentModel.Infrastructure {
    public sealed partial class ExtensionRepository {

        /// <summary>
        /// Represents an item for the <see cref="ExtensionRepository">ExtensionRepository</see>.
        /// </summary>
        public class RepositoryItem {

            private readonly object mSyncRoot = new object();
            private readonly WeakReference mTargetReference;
            private readonly List<object> mExtensions = new List<object>();

            /// <summary>
            /// Gets the key of this instance.
            /// </summary>
            public RepositoryItemTargetKey Key {
                get { return new RepositoryItemTargetKey(Target); }
            }

            /// <summary>
            /// Gets the Target of this instance.
            /// </summary>
            public object Target {
                get { return mTargetReference.Target; }
            }

            /// <summary>
            /// Gets an indication whether the item could be garbage collected because its inner reference was garbage collected.
            /// </summary>
            public bool CouldBeCollectedByGC {
                get { return !mTargetReference.IsAlive; }
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="RepositoryItem">RepositoryItem</see> class, referencing the specified object.
            /// </summary>
            /// <param name="target">The object to track.</param>
            public RepositoryItem(object target) {
                Contract.Requires<ArgumentNullException>(target != null);
                mTargetReference = new WeakReference(target);
            }

            /// <summary>
            /// Gets the extension of the specified type.<br/>
            /// Creates a new instance of the specified type if it was not registered yet.
            /// </summary>
            /// <typeparam name="T">Type of the requested extension.</typeparam>
            /// <returns>Extension</returns>
            public T GetExtension<T>() where T : class, new() {
                lock (mSyncRoot) {
                    return GetExtensionOrNew<T>();
                }
            }

            private T GetExtensionOrNew<T>() where T : class, new() {
                object extension;
                for (int i = 0; i < mExtensions.Count; i++) {
                    extension = mExtensions[i];
                    if (extension is T) {
                        return (T) extension;
                    }
                }
                return NewExtension<T>();
            }

            private T NewExtension<T>() where T : class, new() {
                T newExtension = new T();
                mExtensions.Insert(0, newExtension);
                return newExtension;
            }
        }
    }
}

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 Microsoft Public License (Ms-PL)


Written By
Software Developer
Germany Germany
--------------------------------
Thank you for voting
Best "Everything Else" Article
of September 2014

Comments and Discussions