#region License // Copyright (c) 2010, ClearCanvas Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of ClearCanvas Inc. nor the names of its contributors // may be used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY // OF SUCH DAMAGE. #endregion #region Backport // This file is a backport from a more recent version of a referenced library. // For a complete file change history, please consult the original file. // // File URL: svn://svn.clearcanvas.ca/source/Xian/Trunk/Common/Utilities/UnitTestExtensionFactory.cs // Revision: 13983 // Backport Date: 2010-07-23 16:37:50 #endregion // ReSharper disable SuggestBaseTypeForParameter using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using ClearCanvas.Common; using ClearCanvas.Common.Utilities; namespace Nullstack.ClearCanvasEx.DesktopEx.View.WpfAdapter.Utilities.Backports { /// /// An that returns only extensions that have been explicitly mapped. /// /// /// This is useful in unit test scenarios where precise control over /// creation of extensions is required. Simply create an instance of this class and map individual /// extension types to types. /// internal class CustomExtensionFactory : IExtensionFactory, IDictionary { private static readonly ConstructorInfo _ctorExtensionInfo = typeof (ExtensionInfo).GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new[] {typeof (Type), typeof (Type), typeof (string), typeof (string), typeof (bool)}, null); private readonly Dictionary> _extensionMap = new Dictionary>(); /// /// Instantiates an empty . /// public CustomExtensionFactory() {} /// /// Instantiates an with the provided extensions map. /// public CustomExtensionFactory(IDictionary> extensionMap) { foreach (var entry in extensionMap) foreach (var type in entry.Value) Define(entry.Key, type); } /// /// Instantiates an with the provided extensions map. /// public CustomExtensionFactory(IDictionary extensionMap) { foreach (var entry in extensionMap) Define(entry.Key, entry.Value); } /// /// Defines a type as an extension of the specified type. /// /// The type of the . /// The type of the extension. public void Define(Type extensionPoint, Type extension) { if (!typeof (IExtensionPoint).IsAssignableFrom(extensionPoint)) throw new ArgumentException("Extension point class must implement IExtensionPoint", "extensionPoint"); if (!_extensionMap.ContainsKey(extensionPoint)) _extensionMap.Add(extensionPoint, new List()); _extensionMap[extensionPoint].Add(extension); } /// /// Undefines all extensions for the specified type. /// /// The type of the . /// True if any extensions were undefined; False otherwise. public bool UndefineAll(Type extensionPoint) { if (!typeof (IExtensionPoint).IsAssignableFrom(extensionPoint)) throw new ArgumentException("Extension point class must implement IExtensionPoint", "extensionPoint"); return _extensionMap.Remove(extensionPoint); } /// /// Checks if there are any extensions defined for the specified type. /// /// The type of the . /// True if extensions are undefined; False otherwise. public bool HasExtensions(Type extensionPoint) { if (!typeof (IExtensionPoint).IsAssignableFrom(extensionPoint)) throw new ArgumentException("Extension point class must implement IExtensionPoint", "extensionPoint"); return _extensionMap.ContainsKey(extensionPoint); } /// /// Gets a list of types for which extensions have been defined. /// public ICollection ExtensionPoints { get { return _extensionMap.Keys; } } #region IExtensionFactory Members /// /// Creates one of each type of object that extends the input , /// matching the input ; creates a single extension if is true. /// /// The to create extensions for. /// The filter used to match each extension that is discovered. /// Indicates whether or not to return only the first matching extension that is found. /// public object[] CreateExtensions(ExtensionPoint extensionPoint, ExtensionFilter filter, bool justOne) { var extensionInfos = ListExtensions(extensionPoint, filter); if (justOne && extensionInfos.Length > 1) extensionInfos = new[] {extensionInfos[0]}; var extensions = new ArrayList(); foreach (var extensionInfo in extensionInfos) { try { extensions.Add(Activator.CreateInstance(extensionInfo.ExtensionClass)); } catch (Exception ex) { Platform.Log(LogLevel.Debug, ex, "The extension {0} failed to instantiate. It is probably missing a public default constructor.", extensionInfo.ExtensionClass.FullName); } } return extensions.ToArray(); } /// /// Gets metadata describing all extensions of the input , /// matching the given . /// /// The whose extension metadata is to be retrieved. /// An used to filter out extensions with particular characteristics. /// public virtual ExtensionInfo[] ListExtensions(ExtensionPoint extensionPoint, ExtensionFilter filter) { if (extensionPoint == null) throw new ArgumentNullException("extensionPoint"); var extensionPointType = extensionPoint.GetType(); if (!_extensionMap.ContainsKey(extensionPointType)) return new ExtensionInfo[0]; var extensions = new List(); foreach (var extensionType in _extensionMap[extensionPointType]) { var extensionInfo = (ExtensionInfo) _ctorExtensionInfo.Invoke(new object[] {extensionType, extensionPointType, extensionType.Name, extensionType.AssemblyQualifiedName, true}); if (filter == null || filter.Test(extensionInfo)) extensions.Add(extensionInfo); } return extensions.ToArray(); } #endregion #region IDictionary Members /// /// See . /// /// /// This is separately declared here to support collection initializer syntax. /// public void Add(Type key, Type value) { Define(key, value); } bool IDictionary.ContainsKey(Type key) { return HasExtensions(key); } ICollection IDictionary.Keys { get { return ExtensionPoints; } } bool IDictionary.Remove(Type key) { return UndefineAll(key); } bool IDictionary.TryGetValue(Type key, out Type value) { List list; bool result = _extensionMap.TryGetValue(key, out list); if (result) { value = CollectionUtils.FirstElement(list); return value != null; } value = null; return false; } ICollection IDictionary.Values { get { var list = new List(); foreach (var value in _extensionMap.Values) { list.AddRange(value); } return list.AsReadOnly(); } } Type IDictionary.this[Type key] { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } #endregion #region ICollection> Members void ICollection>.Add(KeyValuePair item) { Define(item.Key, item.Value); } public void Clear() { _extensionMap.Clear(); } bool ICollection>.Contains(KeyValuePair item) { return _extensionMap.ContainsKey(item.Key); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { throw new NotImplementedException(); } int ICollection>.Count { get { return ((IDictionary) this).Values.Count; } } bool ICollection>.IsReadOnly { get { return false; } } bool ICollection>.Remove(KeyValuePair item) { throw new NotImplementedException(); } #endregion #region IEnumerable> Members IEnumerator> IEnumerable>.GetEnumerator() { throw new NotImplementedException(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } #endregion } } // ReSharper restore SuggestBaseTypeForParameter