#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