using System; using System.Collections; using System.Collections.Generic; namespace Inspectron.Settings { public static class Adapters { /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter /// Reference to convert /// Desired type, should be ref type /// Converted reference for the given object or null public static object As(this object reference, Type type) { if (reference == null) return null; if (type == null) throw new ArgumentNullException("type"); // is the adapted object compatible? if (type.IsAssignableFrom(reference.GetType())) return reference; // try to get an adapter var adaptable = reference as IAdaptable; if (adaptable != null) { object adapter = adaptable.GetAdapter(type); if (adapter != null) return adapter; } return null; } /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter /// Desired type, must be ref type /// Reference to convert /// Converted reference for the given object or null public static T As(this object reference) where T : class { if (reference == null) return null; // try a normal cast var converted = reference as T; // if that fails, try to get an adapter if (converted == null) { var adaptable = reference as IAdaptable; if (adaptable != null) converted = adaptable.GetAdapter(typeof(T)) as T; } return converted; } /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter /// Desired type, must be ref type /// Adaptable object /// Converted reference for the given object or null public static T As(this IAdaptable adaptable) where T : class { if (adaptable == null) return null; // try a normal cast var converted = adaptable as T; // if that fails, try to get an adapter if (converted == null) converted = adaptable.GetAdapter(typeof(T)) as T; return converted; } /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter; if none is available, throws an AdaptationException /// Reference to convert /// Desired type, should be ref type /// Converted reference for the given object public static object Cast(this object reference, Type type) { object converted = As(reference, type); if (converted == null) throw new AdaptationException(type.Name + " adapter required"); return converted; } /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter; if none is available, throws an AdaptationException /// Desired type, must be ref type /// Reference to convert /// Converted reference for the given object public static T Cast(this object reference) where T : class { T converted = As(reference); if (converted == null) throw new AdaptationException(typeof(T).Name + " adapter required"); return converted; } /// /// Converts a reference to the given type by first trying a CLR cast, and then /// trying to get an adapter; if none is available, throws an AdaptationException /// Desired type, must be ref type /// Adaptable object /// Converted reference for the given object public static T Cast(this IAdaptable adaptable) where T : class { T converted = As(adaptable); if (converted == null) throw new AdaptationException(typeof(T).Name + " adapter required"); return converted; } /// /// Returns a value indicating if the given reference can be converted to one of /// the desired type /// Reference to test /// Desired type, should be ref type /// True iff the given object can be converted public static bool Is(this object reference, Type type) { return As(reference, type) != null; } /// /// Returns a value indicating if the given reference can be converted to one of /// the desired type /// Adapter type, must be ref type /// Reference to test /// True iff the given object can be converted public static bool Is(this object reference) where T : class { return As(reference) != null; } /// /// Returns a value indicating if the given reference can be converted to one of /// the desired type /// Adapter type, must be ref type /// Adaptable object /// True iff the given object can be converted public static bool Is(this IAdaptable adaptable) where T : class { return As(adaptable) != null; } /// /// Gets all decorators that can convert a reference to the given type /// Reference to convert /// Decorator type, should be ref type /// Enumerable returning all decorators of the given type. /// Decorators are never null. The enumeration may be empty. public static IEnumerable AsAll(this object reference, Type type) { if (reference != null) { // if IDecoratable, use that to get decorators var decoratable = reference as IDecoratable; if (decoratable != null) return decoratable.GetDecorators(type); // is the decorated object compatible? if (type.IsAssignableFrom(reference.GetType())) return new object[] { reference }; } return new List(); } /// /// Gets all decorators that can convert a reference to the given type /// Decorator type, must be ref type /// Reference to convert /// Enumerable returning all decorators of the given type. /// Decorators are never null. The enumeration may be empty. public static IEnumerable AsAll(this object reference) where T : class { if (reference != null) { // if IDecoratable, use that to get decorators var decoratable = reference as IDecoratable; if (decoratable != null) return AsAll(decoratable); // otherwise, cast var t = reference as T; if (t != null) return new T[] { t }; } return new List(); } /// /// Gets an enumeration of all decorators that can convert a reference to the given type /// Decorator type, must be ref type /// Decoratable object /// Enumerable returning all decorators of the given type public static IEnumerable AsAll(this IDecoratable decoratable) where T : class { if (decoratable != null) { foreach (object decorator in decoratable.GetDecorators(typeof(T))) yield return decorator as T; } } /// /// Gets an adapter that converts an enumerable to an enumerable of another type /// Enumerable to adapt /// Adapter type, should be ref type /// Enumerable returning adapted items public static IEnumerable AsIEnumerable(this IEnumerable enumerable, Type type) { if (enumerable != null) { foreach (object item in enumerable) { object adapter = As(item, type); if (adapter != null) yield return adapter; } } } /// /// Returns an enumeration for an adapter that converts an enumerable to an enumerable of another type /// Adapter type, must be ref type /// Enumerable to adapt /// Enumerable returning adapted items public static IEnumerable AsIEnumerable(this IEnumerable enumerable) where T : class { if (enumerable != null) { foreach (object item in enumerable) { T adapter = As(item); if (adapter != null) yield return adapter; } } } /// /// Returns a value indicating if any of the items in the enumerable are /// adaptable to the given type /// Enumerable to adapt /// Adapter type, should be ref type /// True iff any of the items in the enumerable are adaptable to /// the given type public static bool Any(this IEnumerable enumerable, Type type) { if (enumerable != null) { foreach (object item in enumerable) { object adapter = As(item, type); if (adapter != null) return true; } } return false; } /// /// Returns a value indicating if any of the items in the enumerable are /// adaptable to the given type /// Adapter type, must be ref type /// Enumerable to adapt /// True iff any of the items in the enumerable are adaptable to /// the given type public static bool Any(this IEnumerable enumerable) where T : class { return Any(enumerable, typeof(T)); } /// /// Returns a value indicating if all of the items in the enumerable are /// adaptable to the given type /// Enumerable to adapt /// Adapter type, should be ref type /// True iff all of the items in the enumerable are adaptable to /// the given type public static bool All(this IEnumerable enumerable, Type type) { if (enumerable != null) { foreach (object item in enumerable) { object adapter = As(item, type); if (adapter == null) return false; } } return true; } /// /// Returns a value indicating if all of the items in the enumerable are /// adaptable to the given type /// Adapter type, must be ref type /// Enumerable to adapt /// True iff all of the items in the enumerable are adaptable to /// the given type public static bool All(this IEnumerable enumerable) where T : class { return All(enumerable, typeof(T)); } } }