Swapper.NET Logo

Source Code Interfaces ~ PlugInAttributes.cs


using System;
using System.Collections;
using System.Reflection;
using System.IO;
using RevolutionaryStuff.JBT;

namespace RevolutionaryStuff.P2P.Basics
{
	/// 
	/// If an assembly has this attribute, it contains plug-ins
	/// 
	[AttributeUsage(AttributeTargets.Assembly)]
	public class PlugInsAvailableAttribute : Attribute
	{
		/// 
		/// Does the given assembly contain any plugins?
		/// 
		/// The assembly in question
		/// True if it contains plugins
		public static bool HasPlugins(Assembly a)
		{
			if (null==a) throw new ArgumentNullException("a");
			return a.IsDefined(typeof(PlugInsAvailableAttribute), true);
		}
	}

	/// 
	/// If a class has this attribute, it is a plug in for the GFS
	/// 
	[AttributeUsage(AttributeTargets.Class)]
	public class PlugInAttribute : Attribute
	{
		/// 
		/// Gets the set of plugins contained in the given assembly
		/// 
		/// The assembly in question
		/// A dictionary.  The key is the Type, The value is the PlugInAttribute
		public static IDictionary GetPlugInAttributesByType(Assembly a)
		{
			if (null==a) throw new ArgumentNullException("a");
			IDictionary plugInAttributeByType = new System.Collections.Specialized.ListDictionary();
			foreach (Type t in a.GetExportedTypes())
			{
				object[] attrs = t.GetCustomAttributes(typeof(PlugInAttribute), true);
				if (attrs.Length!=1) continue;
				plugInAttributeByType[t] = attrs[0];
			}
			return plugInAttributeByType;
		}

		/// 
		/// Gets the set of plugins contained in the specified assemblies
		/// 
		/// List of loaded assemblies to test
		/// List of assembly names that may contain a plug-in but are not already loaded
		/// Whether to test this unloaded set of plugins in a separate AppDomain or not
		/// A dictionary.  The key is the Type, The value is the PlugInAttribute
		public static IDictionary GetPlugInAttributesByType(Assembly[] assemblies, string[] dllNames, bool testDllsInSeparateAppDomain)
		{
			IDictionary setOfTestedAssemblyFullNames = System.Collections.Specialized.CollectionsUtil.CreateCaseInsensitiveHashtable();
			IDictionary dAll = new System.Collections.Specialized.ListDictionary();
			IList assembliesWithPlugIns = new ArrayList();
			if (assemblies!=null)
			{
				foreach (Assembly a in assemblies)
				{
					setOfTestedAssemblyFullNames[a.FullName] = true;
					try
					{
						setOfTestedAssemblyFullNames[a.Location] = true;
					}
					catch (NotSupportedException){} 
					if (!PlugInsAvailableAttribute.HasPlugins(a)) continue;
					assembliesWithPlugIns.Add(a);
				}
			}
			if (dllNames!=null&&dllNames.Length>0)
			{
				AppDomain appDomain = testDllsInSeparateAppDomain ? AppDomain.CreateDomain("PlugIn Tester Domain", null) : AppDomain.CurrentDomain;
				try
				{
					foreach (string fn in dllNames)
					{
						if (!File.Exists(fn)) continue;
						if (setOfTestedAssemblyFullNames.Contains(fn)) continue;
						Assembly a = null;
						try
						{
							AssemblyName an = AssemblyName.GetAssemblyName(fn);
							string assemblyName = an.FullName;
							if (setOfTestedAssemblyFullNames.Contains(assemblyName)) continue;
							setOfTestedAssemblyFullNames[assemblyName] = true;
							a = appDomain.Load(assemblyName);
							if (!PlugInsAvailableAttribute.HasPlugins(a)) continue;
							if (testDllsInSeparateAppDomain)
							{
								a = AppDomain.CurrentDomain.Load(assemblyName);
							}
							assembliesWithPlugIns.Add(a);
						}
						catch (Exception ex)
						{
							Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManager.Publish(ex);
						}
					}				
				}
				finally
				{
					if (testDllsInSeparateAppDomain)
					{
						AppDomain.Unload(appDomain);
					}
				}
			}
			//Get the dictionary
			foreach (Assembly a in assembliesWithPlugIns)
			{
				foreach (DictionaryEntry de in GetPlugInAttributesByType(a))
				{
					dAll[de.Key] = de.Value;
				}
			}
			return dAll;
		}

		public int Order;

		#region Constructors
		public PlugInAttribute() : this(0)
		{}

		public PlugInAttribute(int order)
		{
			this.Order = order;
		}
		#endregion
	}
}