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; } } } } }