internal PluginDescriptorAlreadyExistsException(PluginDescriptor descriptor) : 
				base(string.Format("The PluginDescriptor '{0}' already exists in the collection.", descriptor.ToString()))
			{
				_descriptor = descriptor;
			}
		/// <summary>
		/// Adds an array of plugin descriptors to the collection.
		/// </summary>
		/// <param name="descriptors">The array of descriptors to add.</param>
		internal void Add(PluginDescriptor[] descriptors)
		{
			if (descriptors == null)
				throw new ArgumentNullException("descriptors");

			foreach (PluginDescriptor descriptor in descriptors)
			{
				this.Add(descriptor);
			}
		}
		/// <summary>
		/// Determines if the collection contains a PluginDescriptor to the same Type as the one specified.
		/// </summary>
		/// <param name="descriptor">The PluginDescriptor to check for</param>
		/// <returns></returns>
		public bool Contains(PluginDescriptor descriptor)
		{
			if (descriptor == null)
				throw new ArgumentNullException("descriptor");
			return (this[descriptor.PluginType] != null);
		}
        /// <summary>
        /// Stops the specified plugin.
        /// </summary>
        /// <param name="progressViewer">The callback object implementing IProgressViewer that will be used to monitor progress.</param>
        /// <param name="descriptor">The descriptor that contains the plugin to stop.</param>
        private static void StopPlugin(IProgressViewer progressViewer, PluginDescriptor descriptor)
        {
			ProgressViewer.SetExtendedDescription(progressViewer, string.Format("Stopping Plugin: '{0}'.", descriptor.PluginName));

            // stop the plugin
            descriptor.PluginInstance.OnStop(PluginContext.Current, new PluginDescriptorEventArgs(descriptor));
        }
		/// <summary>
		/// Adds a PluginDescriptor to the collection.
		/// </summary>
		/// <param name="descriptor">The descriptor to add to the collection</param>
		internal void Add(PluginDescriptor descriptor)
		{
			if (this.Contains(descriptor))
				throw new PluginDescriptorAlreadyExistsException(descriptor);

			lock (base.SyncRoot)
			{
				base.InnerList.Add(descriptor);
			}
		}
 /// <summary>
 /// Determines if the dependencies for a PluginDescriptor are created.
 /// </summary>
 /// <param name="descriptor">The descriptor to check dependencies for.</param>
 /// <param name="descriptors">The collection of PluginDescriptor(s) to check against.</param>
 /// <returns></returns>
 private static bool AreDependenciesCreated(PluginDescriptor descriptor, PluginDescriptorCollection descriptors)
 {
     foreach (Type type in descriptor.PluginDependencies)
         if (descriptors[type].PluginInstance == null)
             return false;            
     return true;
 }
        /// <summary>
        /// Creates an instance of the Type described by the PluginDescriptor and asserts that it derives from Plugin.
        /// </summary>
        /// <param name="progressViewer">The callback object implementing IProgressViewer that will be used to monitor progress.</param>
        /// <param name="descriptor">The PluginDescriptor that contains the Type to create.</param>
        private static void CreatePluginInstance(IProgressViewer progressViewer, PluginDescriptor descriptor)
        {            
            try
            {
                TypeUtilities.AssertTypeIsSubclassOfBaseType(descriptor.PluginType, typeof(Plugin));

				string message = string.Format("Creating Plugin: '{0}'.", descriptor.PluginName);
				ProgressViewer.SetExtendedDescription(progressViewer, message);
				Log.WriteLine(message);

                Plugin plugin = (Plugin)TypeUtilities.CreateInstanceOfType(descriptor.PluginType, Type.EmptyTypes, new object[] {});
                
                descriptor.AttachPluginInstance(plugin);
            }
            catch(Exception ex)
            {
                Log.WriteLine(ex);
            }
        }
//		/// <summary>
//		/// Marks the descriptor if it is missing a dependency
//		/// </summary>
//		/// <param name="descriptor">The descriptor to check</param>
//		/// <param name="descriptors">The collection of PluginDescriptors to check against</param>
//		private static void MarkDescriptorIfMissingDependency(PluginDescriptor descriptor, PluginDescriptorCollection descriptors)
//		{
//            // we may already know that 
//            if (descriptor.IsMissingDependency)
//                return;
//
//			// check each Type the Plugin depends upon to determine if it is missing
//			foreach(Type type in descriptor.PluginDependencies)
//			{
//				// if the dependency Type is equivalent to Missing, then there is an Assembly reference missing
//				if ((object)type == Type.Missing)
//				{
//					// we know the plugin can't be started now so we're done with this one
//					descriptor.IsMissingDependency = true;
//					return;
//				}
//
//				// check each Type the Plugin depends upon to determine if the Type is listed somewhere in the other descriptors
//				// it is possible the Type reference could be valid because the correct Assembly is loaded, but the Plugin that is
//				// required isn't being exported as a Plugin yet. Sometimes the developers forget to export their plugins.
//				bool found = false;
//				foreach(PluginDescriptor otherDescriptor in descriptors)
//				{
//					// if some other descriptor's PluginType is the Type of this dependency
//					if (otherDescriptor.PluginType == type)
//					{
//						// and we aren't comparing the same descriptor
//						if (otherDescriptor != descriptor)
//						{
//							// then this particular dependency is exported and is in the list of descriptors 
//							found = true;
//							break;
//						}
//					}					
//				}
//				
//				// if the Type wasn't found in the list of descriptors then this descriptor's Plugin is missing a dependency
//				if (!found)
//				{
//					// we know the plugin can't be started now so we're done with this one
//					descriptor.IsMissingDependency = true;
//					return;
//				}
//			}
//		}

		/// <summary>
		/// Marks a descriptor if is is circularly dependent with any other descriptor
		/// </summary>
		/// <param name="descriptor">The descriptor to check</param>
		/// <param name="descriptors">The collection of PluginDescriptors to check against</param>
		private static void MarkDescriptorIfCircularlyDependent(PluginDescriptor descriptor, PluginDescriptorCollection descriptors)
		{
			// check each dependency in that descriptor depends on
			foreach(Type type in descriptor.PluginDependencies)
			{
				// against all the other descriptors
				foreach(PluginDescriptor otherDescriptor in descriptors)
				{
					// when we find a descriptor that describes the Type the first descriptor needs
					if (otherDescriptor.PluginType == type)
					{
						// it better not depend on the first
						if (otherDescriptor.DependsOn(descriptor))
						{
							// if it does, it's a circular dependency which we cannot have
							descriptor.IsCircularlyDependent = true;
							return;
						}
					}
				}
			}			
		}
		/// <summary>
		/// Marks a descriptor if it has dependencies that themselves are missing dependencies or are circularly dependent
		/// </summary>
		/// <param name="descriptor">The descriptor to check</param>
		/// <param name="descriptors">The collection of PluginDescriptors to check against</param>
		private static void MarkDescriptorIfDependenciesAreMissingDependencyOrAreCircularlyDependent(PluginDescriptor descriptor, PluginDescriptorCollection descriptors)
		{
			// check each dependency in that descriptor depends on
			foreach(Type type in descriptor.PluginDependencies)
			{
				// against all the other descriptors
				foreach(PluginDescriptor otherDescriptor in descriptors)
				{
					// when we find a descriptor that describes the Type the first descriptor needs
					if (otherDescriptor.PluginType == type)
					{
						// the other dependency better not be missing a dependency
						if (otherDescriptor.IsMissingDependency)
						{
							// if it does, the whole chain is jacked 
							descriptor.IsDependentOnTypeThatIsMissingDependency = true;
							return;
						}
						
						// the other dependency better not be circularly dependent
						if (otherDescriptor.IsCircularlyDependent)
						{
							// if it does, the whole chain is jacked 
							descriptor.IsDependentOnTypeThatIsCircularlyDependent = true;
							return;
						}
					}
				}
			}
		}
		/// <summary>
		/// Creates PluginDescriptors from each Plugin Type specified.
		/// </summary>
		/// <param name="progressViewer">The callback object implementing IProgressViewer that will be used to monitor progress.</param>
		/// <param name="types">The collection of Plugin Types to create descriptors for.</param>
		/// <returns></returns>
		public static PluginDescriptorCollection CreatePluginDescriptors(IProgressViewer progressViewer, TypeCollection types)
		{
			PluginDescriptorCollection descriptors = new PluginDescriptorCollection();
			foreach (Type type in types)
			{
				try
				{
					string message = string.Format("Creating PluginDescriptor, Type: '{0}'.", type.FullName);
                    ProgressViewer.SetExtendedDescription(progressViewer, message);
					Log.WriteLine(message);

                    PluginDescriptor descriptor = new PluginDescriptor(type);

                    descriptors.Add(descriptor);
				}
				catch(Exception ex)
				{
					Log.WriteLine(ex);
				}
			}
			return descriptors;
		}
		/// <summary>
		/// Initializes a new instance of the PluginDescriptorEventArgs class
		/// </summary>
		/// <param name="descriptor"></param>
		public PluginDescriptorEventArgs(PluginDescriptor descriptor)
		{
			_descriptor = descriptor;
		}
		/// <summary>
		/// Sorts an array of PluginDescriptors from least dependent first to most dependent last, or vice versa.
		/// </summary>
		/// <param name="descriptors">The array of descriptors to sort</param>
		/// <param name="leastDependentFirst">The order in which to sort them</param>
		/// <returns></returns>
		public static bool Sort(PluginDescriptor[] descriptors, bool leastDependentFirst)
		{
			try
			{
				for (int i = 0; i < descriptors.Length - 1; i++)
				{
					for (int j = i + 1; j < descriptors.Length; j++)
					{
						bool dependsOn = descriptors[i].DependsOn(descriptors[j]);
						if ((leastDependentFirst ? dependsOn : !dependsOn))
						{
							// swap i with j, where i=1 and j=2
							PluginDescriptor descriptor = descriptors[j];
							descriptors[j] = descriptors[i];
							descriptors[i] = descriptor;
						}
					}
				}
				
				return true;
			}
			catch (Exception ex)
			{
				Log.WriteLine(ex);
			}
			return false;
		}
		/// <summary>
		/// Determines if this Plugin depends upon the PluginType described by the specified PluginDescriptor.
		/// </summary>
		/// <param name="descriptor">The PluginDescriptor to check against this PluginDescriptor's dependencies</param>
		/// <returns>true if this descriptor depends on the specified descriptor's Type</returns>
		internal bool DependsOn(PluginDescriptor descriptor)
		{
			try
			{
				//Log.WriteLine("Determining if Type '{0}' depends on Type '{1}'", _type.Name, descriptor.PluginType.Name);

				foreach (Type type in _dependencies)
					if (Type.Equals(type, descriptor.PluginType))
					{
						//Log.WriteLine(string.Format("'{0}' depends on '{1}'", this.PluginType.Name, type.Name));
						return true;
					}
			}
			catch (Exception ex)
			{
				Log.WriteLine(ex);
			}
				//if ((object)type != Type.Missing && type == descriptor.PluginType)
				//    return true;
			return false;
		}
        /// <summary>
        /// Marks a descriptor if it has dependencies that themselves are missing dependencies or are circularly dependent
        /// </summary>
        /// <param name="descriptor">The descriptor to check</param>
        /// <param name="descriptors">The collection of PluginDescriptors to check against</param>
        private static void MarkDescriptorIfDependenciesAreMissingDependencyOrAreCircularlyDependent(PluginDescriptor descriptor, PluginDescriptorCollection descriptors)
        {
            // check each dependency in that descriptor depends on
            foreach (Type type in descriptor.PluginDependencies)
            {
                // against all the other descriptors
                foreach (PluginDescriptor otherDescriptor in descriptors)
                {
                    // when we find a descriptor that describes the Type the first descriptor needs
                    if (otherDescriptor.PluginType == type)
                    {
                        // the other dependency better not be missing a dependency
                        if (otherDescriptor.IsMissingDependency)
                        {
                            // if it does, the whole chain is jacked
                            descriptor.IsDependentOnTypeThatIsMissingDependency = true;
                            return;
                        }

                        // the other dependency better not be circularly dependent
                        if (otherDescriptor.IsCircularlyDependent)
                        {
                            // if it does, the whole chain is jacked
                            descriptor.IsDependentOnTypeThatIsCircularlyDependent = true;
                            return;
                        }
                    }
                }
            }
        }