Click here to Skip to main content
15,881,812 members
Articles / Programming Languages / C#

CodeDOM Classes for Solution and Project Files (Part 5)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
30 Nov 2012CDDL7 min read 29.9K   1.2K   18  
CodeDOM objects for VS Solution and Project files.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System;
using System.Collections;
using System.Reflection;

namespace Nova.CodeDOM
{
    /// <summary>
    /// Represents a group of named code objects (<see cref="INamedCodeObject"/>s and/or <see cref="MemberInfo"/>s)
    /// with the same name, such as overloaded methods or other name collisions.
    /// </summary>
    /// <remarks>
    /// Used by <see cref="NamedCodeObjectDictionary"/> to hold groups of child <see cref="INamedCodeObject"/>s with the same name,
    /// and also by various Get() and Find() type methods to return collections of <see cref="INamedCodeObject"/>s and/or
    /// <see cref="MemberInfo"/>s with the same name.
    /// </remarks>
    public class NamedCodeObjectGroup : INamedCodeObject, ICollection
    {
        #region /* FIELDS */

        /// <summary>
        /// The list of code objects with the same name.
        /// </summary>
        protected ArrayList _list = new ArrayList();

        #endregion

        #region /* CONSTRUCTORS */

        /// <summary>
        /// Create an empty <see cref="NamedCodeObjectGroup"/>.
        /// </summary>
        public NamedCodeObjectGroup()
        { }

        /// <summary>
        /// Create a <see cref="NamedCodeObjectGroup"/>, adding the specified object to it.
        /// </summary>
        public NamedCodeObjectGroup(object obj)
        {
            Add(obj);
        }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// The name of the <see cref="NamedCodeObjectGroup"/>.
        /// </summary>
        public string Name
        {
            get
            {
                object obj = _list[0];
                string name;
                if (obj is INamedCodeObject)
                    name = ((INamedCodeObject)obj).Name;
                else if (obj is MemberInfo)
                    name = ((MemberInfo)obj).Name;
                else
                    name = null;
                return name;
            }
        }

        /// <summary>
        /// The descriptive category of the code object.
        /// </summary>
        public string Category
        {
            get { return "ambiguity"; }
        }

        /// <summary>
        /// The number of items in the group.
        /// </summary>
        public int Count
        {
            get { return _list.Count; }
        }

        /// <summary>
        /// Get the first item in the group.
        /// </summary>
        public object First
        {
            get { return _list[0]; }
        }

        /// <summary>
        /// True if access to the <see cref="ICollection"/> is synchronized.
        /// </summary>
        public virtual bool IsSynchronized
        {
            get { return false; }
        }

        /// <summary>
        /// Gets an object that can be used to synchronize access to the <see cref="ICollection"/>.
        /// </summary>
        public virtual object SyncRoot
        {
            get { return this; }
        }

        #endregion

        #region /* METHODS */

        /// <summary>
        /// Add the specified <see cref="INamedCodeObject"/> to the group.
        /// </summary>
        public void Add(INamedCodeObject namedCodeObject)
        {
            _list.Add(namedCodeObject);
        }

        /// <summary>
        /// Add the specified <see cref="MemberInfo"/> to the group.
        /// </summary>
        public void Add(MemberInfo memberInfo)
        {
            _list.Add(memberInfo);
        }

        /// <summary>
        /// Add an object to the group.
        /// </summary>
        /// <param name="obj">The object being added.</param>
        public void Add(object obj)
        {
            if (obj is IEnumerable)
                AddRange((IEnumerable)obj);
            else if (obj != null)
                _list.Add(obj);
        }

        protected void AddRange(IEnumerable collection)
        {
            if (collection != null)
            {
                // Call the Add method for each member, allowing for nested
                // arrays and/or collections.
                foreach (object obj in collection)
                    Add(obj);
            }
        }

        /// <summary>
        /// This method is not supported for this type.
        /// </summary>
        public SymbolicRef CreateRef(bool isFirstOnLine)
        {
            throw new Exception("Can't create a reference to a NamedCodeObjectGroup!");
        }

        /// <summary>
        /// This method is not supported for this type.
        /// </summary>
        public SymbolicRef CreateRef()
        {
            return CreateRef(false);
        }

        /// <summary>
        /// Remove all items from the group.
        /// </summary>
        public void Clear()
        {
            _list.Clear();
        }

        /// <summary>
        /// Copy the objects in the group to the specified array, starting at the specified offset.
        /// </summary>
        /// <param name="array">The array to copy into.</param>
        /// <param name="index">The starting index in the array.</param>
        public virtual void CopyTo(Array array, int index)
        {
            if (array == null)
                throw new ArgumentNullException("array", "Null array reference");
            if (index < 0)
                throw new ArgumentOutOfRangeException("index", "Index is out of range");
            if (array.Rank > 1)
                throw new ArgumentException("Array is multi-dimensional", "array");

            foreach (object obj in this)
                array.SetValue(obj, index++);
        }

        /// <summary>
        /// Check if the group contains the specified code object.
        /// </summary>
        /// <param name="codeObject">The code object being searched for.</param>
        /// <returns>True if the group contains the object, otherwise false.</returns>
        public bool Contains(CodeObject codeObject)
        {
            // NOTE: A bug in .NET causes an exception if Equals is called (which Contains uses) to
            // compare a MethodInfo for a generic method declaration to any non-MethodInfo object.
            // We currently only call this method for CodeObjects, so we look for them specifically
            // to avoid the bug.
            //return _list.Contains(obj);
            if (_list.Count > 0)
            {
                foreach (object obj in _list)
                {
                    if (obj is CodeObject && obj.Equals(codeObject))
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Get an enumerator for the objects in the group.
        /// </summary>
        public IEnumerator GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        /// <summary>
        /// Remove the specified object from the group.
        /// </summary>
        public void Remove(object obj)
        {
            _list.Remove(obj);
        }

        /// <summary>
        /// Remove the object at the specified index from the group.
        /// </summary>
        public void RemoveAt(int index)
        {
            _list.RemoveAt(index);
        }

        /// <summary>
        /// Get the object in the group at the specified index.
        /// </summary>
        public object this[int index]
        {
            get { return _list[index]; }
        }

        /// <summary>
        /// Add the <see cref="CodeObject"/> to the specified dictionary.
        /// </summary>
        public virtual void AddToDictionary(NamedCodeObjectDictionary dictionary)
        {
            dictionary.Add(Name, this);
        }

        /// <summary>
        /// Remove the <see cref="CodeObject"/> from the specified dictionary.
        /// </summary>
        public virtual void RemoveFromDictionary(NamedCodeObjectDictionary dictionary)
        {
            dictionary.Remove(Name, this);
        }

        /// <summary>
        /// This method always returns null for this type.
        /// </summary>
        public T FindParent<T>() where T : CodeObject
        {
            return null;
        }

        /// <summary>
        /// Get the full name of the <see cref="INamedCodeObject"/>, including any namespace name.
        /// </summary>
        public string GetFullName(bool descriptive)
        {
            return Name;
        }

        /// <summary>
        /// Get the full name of the <see cref="INamedCodeObject"/>, including any namespace name.
        /// </summary>
        public string GetFullName()
        {
            return Name;
        }

        #endregion

        #region /* STATIC METHODS */

        /// <summary>
        /// Add a source object or group to a target object or group, converting the target into a group if necessary.
        /// </summary>
        /// <param name="target">The target object or group.</param>
        /// <param name="source">The source object or group.</param>
        public static void Add(ref object target, object source)
        {
            if (target == null)
            {
                if (source is ICollection)
                {
                    if (((ICollection)source).Count > 0)
                        target = new NamedCodeObjectGroup(source);
                }
                else
                    target = source;
            }
            else if (source != null && !(source is ICollection && ((ICollection)source).Count == 0))
            {
                if (!(target is NamedCodeObjectGroup))
                    target = new NamedCodeObjectGroup(target);
                ((NamedCodeObjectGroup)target).Add(source);
            }
        }

        /// <summary>
        /// Add a source object or group to a target object or group, converting the target into a group if necessary.
        /// </summary>
        /// <param name="target">The target object or group.</param>
        /// <param name="source">The source object or group.</param>
        public static void Add(ref INamedCodeObject target, INamedCodeObject source)
        {
            if (target == null)
            {
                if (source is NamedCodeObjectGroup)
                    target = new NamedCodeObjectGroup(source);
                else
                    target = source;
            }
            else if (source != null)
            {
                if (!(target is NamedCodeObjectGroup))
                    target = new NamedCodeObjectGroup(target);
                ((NamedCodeObjectGroup)target).Add(source);
            }
        }

        #endregion
    }
}

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 Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions