/Utilities/Collections/CovariantExtensions.cs
C# | 370 lines | 204 code | 30 blank | 136 comment | 1 complexity | 0325cfe1dcdd099af14f3c8752160dd2 MD5 | raw file
Possible License(s): Apache-2.0
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Collections
- {
- /// <summary>
- /// Provides extensions to implement covariance of generic types, make sure
- /// to use this namespace when using this extensions.
- /// </summary>
- public static class CovariantExtensions
- {
- #region CollectionInterfaceAdapter Class
- /// <summary>
- /// Allows for covariance of generic ICollections. Adapts a collection of
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// Credits go to the Umbrella (http://codeplex.com/umbrella) project
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- private class CollectionInterfaceAdapter<T, U>
- : EnumerableInterfaceAdapter<T, U>, ICollection<U>
- where T : U
- {
- #region Count (Public)
- /// <summary>
- /// Count
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- public int Count
- {
- get
- {
- return Target.Count;
- }
- }
- #endregion
-
- #region IsReadOnly (Public)
- /// <summary>
- /// Is read only
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- public bool IsReadOnly
- {
- get
- {
- return Target.IsReadOnly;
- }
- }
- #endregion
-
- #region Private
-
- #region Target (Private)
- /// <summary>
- /// Target
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- private new ICollection<T> Target
- {
- get;
- set;
- }
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Collection interface adapter
- /// </summary>
- /// <param name="target">Target collection to create from</param>
- public CollectionInterfaceAdapter(ICollection<T> target)
- : base(target)
- {
- }
- #endregion
-
- #region ICollection<U> Members
- /// <summary>
- /// Add
- /// </summary>
- /// <param name="item">Item</param>
- public void Add(U item)
- {
- Target.Add((T)item);
- }
-
- /// <summary>
- /// Clear
- /// </summary>
- public void Clear()
- {
- Target.Clear();
- }
-
- /// <summary>
- /// Contains
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>True if the item was found, false otherwise</returns>
- public bool Contains(U item)
- {
- return Target.Contains((T)item);
- }
-
- /// <summary>
- /// Copy to array.
- /// </summary>
- /// <param name="array">Array to copy into</param>
- /// <param name="arrayIndex">Array index to start copying into</param>
- public void CopyTo(U[] array, int arrayIndex)
- {
- int index = 0;
- foreach (U element in Target)
- {
- if (index >= arrayIndex)
- {
- array[index] = element;
- }
- index++;
- }
- }
-
- /// <summary>
- /// Remove item from the target collection.
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>
- /// True if removing the item succeeded, false otherwise.
- /// </returns>
- public bool Remove(U item)
- {
- return Target.Remove((T)item);
- }
- #endregion
- }
- #endregion
-
- #region EnumerableInterfaceAdapter Class
- /// <summary>
- /// Allows for covariance of generic IEnumerables. Adapts a collection of type
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- private class EnumerableInterfaceAdapter<T, U> : IEnumerable<U>
- where T : U
- {
- #region Target (Public)
- /// <summary>
- /// Target
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- public IEnumerable<T> Target
- {
- get;
- set;
- }
- #endregion
-
- #region Constructors
- /// <summary>
- /// Enumerable interface adapter
- /// </summary>
- /// <param name="target">Target</param>
- public EnumerableInterfaceAdapter(IEnumerable<T> target)
- {
- Target = target;
- }
- #endregion
-
- #region IEnumerable Members
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- #endregion
-
- #region IEnumerable<U> Members
- /// <summary>
- /// Get enumerator
- /// </summary>
- /// <returns>Enumerator item for the target collection.</returns>
- public IEnumerator<U> GetEnumerator()
- {
- foreach (T item in Target)
- {
- yield return item;
- }
- }
- #endregion
- }
- #endregion
-
- #region ListInterfaceAdapter Class
- /// <summary>
- /// Allows for covariance of generic ILists. Adapts a collection of type
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- private class ListInterfaceAdapter<T, U>
- : CollectionInterfaceAdapter<T, U>,
- IList<U>
- where T : U
- {
- #region Item (Public)
- /// <summary>
- /// Get Item via indexer.
- /// </summary>
- /// <param name="index">Index</param>
- /// <returns>Item</returns>
- public U this[int index]
- {
- get
- {
- return Target[index];
- }
- set
- {
- Target[index] = (T)value;
- }
- }
- #endregion
-
- #region Private
-
- #region Target (Private)
- /// <summary>
- /// Target
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- private new IList<T> Target
- {
- get;
- set;
- }
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// List interface adapter
- /// </summary>
- /// <param name="target">Target list to work on</param>
- public ListInterfaceAdapter(IList<T> target)
- : base(target)
- {
- }
- #endregion
-
- #region IList<U> Members
- /// <summary>
- /// Index of item
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>Index of the item if found</returns>
- public int IndexOf(U item)
- {
- return Target.IndexOf((T)item);
- }
-
- /// <summary>
- /// Insert
- /// </summary>
- /// <param name="index">Index</param>
- /// <param name="item">Item</param>
- public void Insert(int index, U item)
- {
- Target.Insert(index, (T)item);
- }
-
- /// <summary>
- /// Remove at
- /// </summary>
- /// <param name="index">Index</param>
- public void RemoveAt(int index)
- {
- Target.RemoveAt(index);
- }
- #endregion
- }
- #endregion
-
- #region ToCovariant (Static)
- /// <summary>
- /// Allows for covariance of generic ICollections. Adapts a collection of
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- /// <returns>Covariant collection created from the source.</returns>
- public static ICollection<U> ToCovariant<T, U>(this ICollection<T> source)
- where T : U
- {
- return new CollectionInterfaceAdapter<T, U>(source);
- }
-
- /// <summary>
- /// Allows for covariance of generic ILists. Adapts a collection of type
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- /// <param name="source">Source</param>
- /// <returns>Covariant list from the source list.</returns>
- public static IList<U> ToCovariant<T, U>(this IList<T> source)
- where T : U
- {
- return new ListInterfaceAdapter<T, U>(source);
- }
-
- /// <summary>
- /// Allows for covariance of generic IEnumerables. Adapts a collection of
- /// <typeparam name="T" /> into a collection of type <typeparam name="U" />
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <typeparam name="U">U</typeparam>
- /// <param name="source">Source</param>
- /// <returns>Covariant enumerable from the source enumerable.</returns>
- public static IEnumerable<U> ToCovariant<T, U>(this IEnumerable<T> source)
- where T : U
- {
- return new EnumerableInterfaceAdapter<T, U>(source);
- }
- #endregion
-
- /// <summary>
- /// CovariantExtensions Tests
- /// </summary>
- internal class CovariantExtensionsTests
- {
- #region Helpers
- private interface IFoo
- {
- }
- #endregion
-
- #region Helpers
- private interface IBar : IFoo
- {
- }
- #endregion
-
- #region ShouldConvertCollections
- /// <summary>
- /// Should convert collections
- /// </summary>
- [Test]
- public void ShouldConvertCollections()
- {
- var barcol = new Collection<IBar>();
- IList<IFoo> foocol = barcol.ToCovariant<IBar, IFoo>();
- ICollection<IFoo> foo2 = barcol.ToCovariant<IBar, IFoo>();
- IEnumerable<IFoo> foo3 = barcol.ToCovariant<IBar, IFoo>();
- }
- #endregion
- }
- }
- }
-