diff options
author | Lluis Sanchez <lluis@novell.com> | 2010-05-27 21:16:57 +0400 |
---|---|---|
committer | Lluis Sanchez <lluis@novell.com> | 2010-05-27 21:16:57 +0400 |
commit | 38fdcb4cdf655fdd218a4938bbafaf02cc9f056d (patch) | |
tree | be9514bc770ae30f729075aaecbf377c7a8eab6a | |
parent | 50bc9e60c8bef251892b8d97c133f2a70ebae74f (diff) |
* Mono.Addins/AddinManager.cs:
* Mono.Addins/ConditionType.cs:
* Mono.Addins/ExtensionNode.cs:
* Mono.Addins/ExtensionContext.cs:
* Mono.Addins/ExtensionAttribute.cs:
* Mono.Addins/AddinRootAttribute.cs:
* Mono.Addins/ConsoleProgressStatus.cs:
* Mono.Addins/CustomExtensionAttribute.cs:
* Mono.Addins/ExtensionAttributeAttribute.cs: More documentation.
svn path=/trunk/mono-addins/; revision=158047
-rw-r--r-- | Mono.Addins/ChangeLog | 13 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinManager.cs | 6 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/AddinRootAttribute.cs | 24 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ConditionType.cs | 28 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ConsoleProgressStatus.cs | 15 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/CustomExtensionAttribute.cs | 16 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionAttribute.cs | 73 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionAttributeAttribute.cs | 21 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionContext.cs | 425 | ||||
-rw-r--r-- | Mono.Addins/Mono.Addins/ExtensionNode.cs | 184 |
10 files changed, 792 insertions, 13 deletions
diff --git a/Mono.Addins/ChangeLog b/Mono.Addins/ChangeLog index 2a6c532..357ca38 100644 --- a/Mono.Addins/ChangeLog +++ b/Mono.Addins/ChangeLog @@ -1,5 +1,18 @@ 2010-05-27 Lluis Sanchez Gual <lluis@novell.com> + * Mono.Addins/AddinManager.cs: + * Mono.Addins/ConditionType.cs: + * Mono.Addins/ExtensionNode.cs: + * Mono.Addins/ExtensionContext.cs: + * Mono.Addins/ExtensionAttribute.cs: + * Mono.Addins/AddinRootAttribute.cs: + * Mono.Addins/ConsoleProgressStatus.cs: + * Mono.Addins/CustomExtensionAttribute.cs: + * Mono.Addins/ExtensionAttributeAttribute.cs: More + documentation. + +2010-05-27 Lluis Sanchez Gual <lluis@novell.com> + * Mono.Addins/AddinEngine.cs: * Mono.Addins/AddinManager.cs: * Mono.Addins/AddinRegistry.cs: diff --git a/Mono.Addins/Mono.Addins/AddinManager.cs b/Mono.Addins/Mono.Addins/AddinManager.cs index 8745085..538e265 100644 --- a/Mono.Addins/Mono.Addins/AddinManager.cs +++ b/Mono.Addins/Mono.Addins/AddinManager.cs @@ -297,7 +297,7 @@ namespace Mono.Addins /// <param name="path"> /// An extension path. /// </param> - /// <param name="type"> + /// <param name="expectedNodeType"> /// Expected node type. /// </param> /// <returns> @@ -308,10 +308,10 @@ namespace Mono.Addins /// It will throw a InvalidOperationException if the type of one of /// the registered nodes is not assignable to the provided type. /// </remarks> - public static ExtensionNodeList GetExtensionNodes (string path, Type type) + public static ExtensionNodeList GetExtensionNodes (string path, Type expectedNodeType) { AddinEngine.CheckInitialized (); - return AddinEngine.GetExtensionNodes (path, type); + return AddinEngine.GetExtensionNodes (path, expectedNodeType); } /// <summary> diff --git a/Mono.Addins/Mono.Addins/AddinRootAttribute.cs b/Mono.Addins/Mono.Addins/AddinRootAttribute.cs index 4725742..9cf1e79 100644 --- a/Mono.Addins/Mono.Addins/AddinRootAttribute.cs +++ b/Mono.Addins/Mono.Addins/AddinRootAttribute.cs @@ -31,17 +31,41 @@ using System; namespace Mono.Addins { + /// <summary> + /// Marks an assembly as being an add-in root. + /// </summary> + /// <remarks> + /// An add-in root is an assemly which can be extended by add-ins. + /// </remarks> [AttributeUsage (AttributeTargets.Assembly)] public class AddinRootAttribute: AddinAttribute { + /// <summary> + /// Initializes a new instance + /// </summary> public AddinRootAttribute () { } + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="id"> + /// Identifier of the add-in root + /// </param> public AddinRootAttribute (string id): base (id) { } + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="id"> + /// Identifier of the add-in root + /// </param> + /// <param name="version"> + /// Version of the add-in root + /// </param> public AddinRootAttribute (string id, string version): base (id, version) { } diff --git a/Mono.Addins/Mono.Addins/ConditionType.cs b/Mono.Addins/Mono.Addins/ConditionType.cs index ebf38a4..6f03830 100644 --- a/Mono.Addins/Mono.Addins/ConditionType.cs +++ b/Mono.Addins/Mono.Addins/ConditionType.cs @@ -34,13 +34,41 @@ using System.Collections; namespace Mono.Addins { + /// <summary> + /// A condition evaluator. + /// </summary> + /// <remarks> + /// Add-ins may use conditions to register nodes in an extension point which + /// are only visible under some contexts. For example, an add-in registering + /// a custom menu option to the main menu of a sample text editor might want + /// to make that option visible only for some kind of files. To allow add-ins + /// to do this kind of check, the host application needs to define a new condition. + /// </remarks> public abstract class ConditionType { internal event EventHandler Changed; string id; + /// <summary> + /// Evaluates the condition. + /// </summary> + /// <param name="conditionNode"> + /// Condition node information. + /// </param> + /// <returns> + /// 'true' if the condition is satisfied. + /// </returns> public abstract bool Evaluate (NodeElement conditionNode); + /// <summary> + /// Notifies that the condition has changed, and that it has to be re-evaluated. + /// </summary> + /// This method must be called when there is a change in the state that determines + /// the result of the evaluation. When this method is called, all node conditions + /// depending on it are reevaluated and the corresponding events for adding or + /// removing extension nodes are fired. + /// <remarks> + /// </remarks> public void NotifyChanged () { if (Changed != null) diff --git a/Mono.Addins/Mono.Addins/ConsoleProgressStatus.cs b/Mono.Addins/Mono.Addins/ConsoleProgressStatus.cs index d6ab9f0..e3b01da 100644 --- a/Mono.Addins/Mono.Addins/ConsoleProgressStatus.cs +++ b/Mono.Addins/Mono.Addins/ConsoleProgressStatus.cs @@ -31,11 +31,20 @@ using System; namespace Mono.Addins { + /// <summary> + /// An IProgressStatus class which writes output to the console. + /// </summary> public class ConsoleProgressStatus: MarshalByRefObject, IProgressStatus { bool canceled; int logLevel; + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="verboseLog"> + /// Set to true to enabled verbose log + /// </param> public ConsoleProgressStatus (bool verboseLog) { if (verboseLog) @@ -44,6 +53,12 @@ namespace Mono.Addins logLevel = 1; } + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="logLevel"> + /// Verbosity level. 0: not verbose, 1: normal, >1 extra verbose + /// </param> public ConsoleProgressStatus (int logLevel) { this.logLevel = logLevel; diff --git a/Mono.Addins/Mono.Addins/CustomExtensionAttribute.cs b/Mono.Addins/Mono.Addins/CustomExtensionAttribute.cs index 11491b3..f42fc32 100644 --- a/Mono.Addins/Mono.Addins/CustomExtensionAttribute.cs +++ b/Mono.Addins/Mono.Addins/CustomExtensionAttribute.cs @@ -28,24 +28,40 @@ using System; namespace Mono.Addins { + /// <summary> + /// Base class for custon extension attributes. + /// </summary> + /// <remarks> + /// Custom extension attributes can be used to declare extensions with custom metadata. + /// All custom extension attributes must subclass CustomExtensionAttribute. + /// </remarks> public class CustomExtensionAttribute: Attribute { string id; string insertBefore; string insertAfter; + /// <summary> + /// Identifier of the node + /// </summary> [NodeAttributeAttribute ("id")] public string Id { get { return id; } set { id = value; } } + /// <summary> + /// Identifier of the node before which this node has to be placed + /// </summary> [NodeAttributeAttribute ("insertbefore")] public string InsertBefore { get { return insertBefore; } set { insertBefore = value; } } + /// <summary> + /// Identifier of the node after which this node has to be placed + /// </summary> [NodeAttributeAttribute ("insertafter")] public string InsertAfter { get { return insertAfter; } diff --git a/Mono.Addins/Mono.Addins/ExtensionAttribute.cs b/Mono.Addins/Mono.Addins/ExtensionAttribute.cs index 0c2de5f..155ca04 100644 --- a/Mono.Addins/Mono.Addins/ExtensionAttribute.cs +++ b/Mono.Addins/Mono.Addins/ExtensionAttribute.cs @@ -31,6 +31,13 @@ using System; namespace Mono.Addins { + /// <summary> + /// Declares a type extension. + /// </summary> + /// <remarks> + /// When applied to a class, specifies that the class is an extension + /// class to be registered in a matching extension point. + /// </remarks> [AttributeUsage (AttributeTargets.Class, AllowMultiple=true)] public class ExtensionAttribute: Attribute { @@ -46,41 +53,103 @@ namespace Mono.Addins { } + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="path"> + /// Path of the extension point. + /// </param> + /// <remarks>The path is only required if there are several extension points defined for the same type.</remarks> public ExtensionAttribute (string path) { this.path = path; } + /// <summary> + /// Initializes a new instance + /// </summary> + /// <param name="type"> + /// Type defining the extension point being extended + /// </param> + /// <remarks> + /// This constructor can be used to explicitly specify the type that defines the extension point + /// to be extended. By default, Mono.Addins will try to find any extension point defined in any + /// of the base classes or interfaces. The type parameter can be used when there is more than one + /// base type providing an extension point. + /// </remarks> public ExtensionAttribute (Type type) { Type = type; } + /// <summary> + /// Path of the extension point being extended + /// </summary> + /// <remarks> + /// The path is only required if there are several extension points defined for the same type. + /// </remarks> public string Path { get { return path ?? string.Empty; } set { path = value; } } - + + /// <summary> + /// Name of the extension node + /// </summary> + /// <remarks> + /// Extension points may require extensions to use a specific node name. + /// This is needed when an extension point may contain several different types of nodes. + /// </remarks> public string NodeName { get { return !string.IsNullOrEmpty (nodeName) ? nodeName : "Type"; } set { nodeName = value; } } + /// <summary> + /// Identifier of the extension node. + /// </summary> + /// <remarks> + /// The ExtensionAttribute.InsertAfter and ExtensionAttribute.InsertBefore + /// properties can be used to specify the relative location of a node. The nodes + /// referenced in those properties must be defined either in the add-in host + /// being extended, or in any add-in on which this add-in depends. + /// </remarks> public string Id { get { return id ?? string.Empty; } set { id = value; } } - + + /// <summary> + /// Identifier of the extension node before which this node has to be added in the extension point. + /// </summary> + /// <remarks> + /// The ExtensionAttribute.InsertAfter and ExtensionAttribute.InsertBefore + /// properties can be used to specify the relative location of a node. The nodes + /// referenced in those properties must be defined either in the add-in host + /// being extended, or in any add-in on which this add-in depends. + /// </remarks> public string InsertBefore { get { return insertBefore ?? string.Empty; } set { insertBefore = value; } } + /// <summary> + /// Identifier of the extension node after which this node has to be added in the extension point. + /// </summary> public string InsertAfter { get { return insertAfter ?? string.Empty; } set { insertAfter = value; } } + /// <summary> + /// Type defining the extension point being extended + /// </summary> + /// <remarks> + /// This property can be used to explicitly specify the type that defines the extension point + /// to be extended. By default, Mono.Addins will try to find any extension point defined in any + /// of the base classes or interfaces. This property can be used when there is more than one + /// base type providing an extension point. + /// </remarks> public Type Type { get { return type; } set { type = value; typeName = type.FullName; } diff --git a/Mono.Addins/Mono.Addins/ExtensionAttributeAttribute.cs b/Mono.Addins/Mono.Addins/ExtensionAttributeAttribute.cs index b94c448..65bc5ac 100644 --- a/Mono.Addins/Mono.Addins/ExtensionAttributeAttribute.cs +++ b/Mono.Addins/Mono.Addins/ExtensionAttributeAttribute.cs @@ -28,6 +28,13 @@ using System; namespace Mono.Addins { + /// <summary> + /// Assigns an attribute value to an extension + /// </summary> + /// <remarks> + /// This attribute can be used together with the [Extenion] attribute to specify + /// a value for an attribute of the extension. + /// </remarks> public class ExtensionAttributeAttribute: Attribute { Type targetType; @@ -56,21 +63,33 @@ namespace Mono.Addins Path = path; } + /// <summary> + /// Name of the attribute + /// </summary> public string Name { get { return this.name; } set { this.name = value; } } + /// <summary> + /// Value of the attribute + /// </summary> public string Value { get { return this.val; } set { this.val = value; } } + /// <summary> + /// Path of the extension for which the attribute value is being set + /// </summary> public string Path { get { return this.path; } set { this.path = value; } } - + + /// <summary> + /// Type of the extension for which the attribute value is being set + /// </summary> public Type Type { get { return targetType; } set { targetType = value; targetTypeName = targetType.FullName; } diff --git a/Mono.Addins/Mono.Addins/ExtensionContext.cs b/Mono.Addins/Mono.Addins/ExtensionContext.cs index ed6399a..3577bc3 100644 --- a/Mono.Addins/Mono.Addins/ExtensionContext.cs +++ b/Mono.Addins/Mono.Addins/ExtensionContext.cs @@ -35,6 +35,16 @@ using Mono.Addins.Description; namespace Mono.Addins { + /// <summary> + /// An extension context. + /// </summary> + /// <remarks> + /// Extension contexts can be used to query the extension tree + /// using particular condition values. Extension points which + /// declare the availability of a condition type can only be + /// queryed using an extension context which provides an + /// evaluator for that condition. + /// </remarks> public class ExtensionContext { Hashtable conditionTypes = new Hashtable (); @@ -47,6 +57,16 @@ namespace Mono.Addins ArrayList runTimeEnabledAddins; ArrayList runTimeDisabledAddins; + /// <summary> + /// Extension change event. + /// </summary> + /// <remarks> + /// This event is fired when any extension point in the add-in system changes. + /// The event args object provides the path of the changed extension, although + /// it does not provide information about what changed. Hosts subscribing to + /// this event should get the new list of nodes using a query method such as + /// AddinManager.GetExtensionNodes() and then update whatever needs to be updated. + /// </remarks> public event ExtensionEventHandler ExtensionChanged; ~ExtensionContext () @@ -114,6 +134,20 @@ namespace Mono.Addins } } + /// <summary> + /// Registers a new condition in the extension context. + /// </summary> + /// <param name="id"> + /// Identifier of the condition. + /// </param> + /// <param name="type"> + /// Condition evaluator. + /// </param> + /// <remarks> + /// The registered condition will be particular to this extension context. + /// Any event that might be fired as a result of changes in the condition will + /// only be fired in this context. + /// </remarks> public void RegisterCondition (string id, ConditionType type) { type.Id = id; @@ -125,6 +159,19 @@ namespace Mono.Addins type.Changed += new EventHandler (OnConditionChanged); } + /// <summary> + /// Registers a new condition in the extension context. + /// </summary> + /// <param name="id"> + /// Identifier of the condition. + /// </param> + /// <param name="type"> + /// Type of the condition evaluator. Must be a subclass of Mono.Addins.ConditionType. + /// </param> + /// <remarks> + /// The registered condition will be particular to this extension context. Any event + /// that might be fired as a result of changes in the condition will only be fired in this context. + /// </remarks> public void RegisterCondition (string id, Type type) { // Allows delayed creation of condition types @@ -218,6 +265,15 @@ namespace Mono.Addins } } + /// <summary> + /// Returns the extension node in a path + /// </summary> + /// <param name="path"> + /// Location of the node. + /// </param> + /// <returns> + /// The node, or null if not found. + /// </returns> public ExtensionNode GetExtensionNode (string path) { TreeNode node = GetNode (path); @@ -230,27 +286,88 @@ namespace Mono.Addins return null; } + /// <summary> + /// Returns the extension node in a path + /// </summary> + /// <param name="path"> + /// Location of the node. + /// </param> + /// <returns> + /// The node, or null if not found. + /// </returns> public T GetExtensionNode<T> (string path) where T: ExtensionNode { return (T) GetExtensionNode (path); } + /// <summary> + /// Gets extension nodes registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path.> + /// </param> + /// <returns> + /// All nodes registered in the provided path. + /// </returns> public ExtensionNodeList GetExtensionNodes (string path) { return GetExtensionNodes (path, null); } + /// <summary> + /// Gets extension nodes registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <returns> + /// A list of nodes + /// </returns> + /// <remarks> + /// This method returns all nodes registered under the provided path. + /// It will throw a InvalidOperationException if the type of one of + /// the registered nodes is not assignable to the provided type. + /// </remarks> public ExtensionNodeList<T> GetExtensionNodes<T> (string path) where T: ExtensionNode { ExtensionNodeList nodes = GetExtensionNodes (path, typeof(T)); return new ExtensionNodeList<T> (nodes.list); } + /// <summary> + /// Gets extension nodes for a type extension point + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <returns> + /// A list of nodes + /// </returns> + /// <remarks> + /// This method returns all extension nodes bound to the provided type. + /// </remarks> public ExtensionNodeList GetExtensionNodes (Type instanceType) { return GetExtensionNodes (instanceType, typeof(ExtensionNode)); } + /// <summary> + /// Gets extension nodes for a type extension point + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <param name="expectedNodeType"> + /// Expected extension node type + /// </param> + /// <returns> + /// A list of nodes + /// </returns> + /// <remarks> + /// This method returns all nodes registered for the provided type. + /// It will throw a InvalidOperationException if the type of one of + /// the registered nodes is not assignable to the provided node type. + /// </remarks> public ExtensionNodeList GetExtensionNodes (Type instanceType, Type expectedNodeType) { string path = AddinEngine.GetAutoTypeExtensionPoint (instanceType); @@ -259,6 +376,20 @@ namespace Mono.Addins return GetExtensionNodes (path, expectedNodeType); } + /// <summary> + /// Gets extension nodes for a type extension point + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <returns> + /// A list of nodes + /// </returns> + /// <remarks> + /// This method returns all nodes registered for the provided type. + /// It will throw a InvalidOperationException if the type of one of + /// the registered nodes is not assignable to the specified node type argument. + /// </remarks> public ExtensionNodeList<T> GetExtensionNodes<T> (Type instanceType) where T: ExtensionNode { string path = AddinEngine.GetAutoTypeExtensionPoint (instanceType); @@ -267,6 +398,23 @@ namespace Mono.Addins return new ExtensionNodeList<T> (GetExtensionNodes (path, typeof (T)).list); } + /// <summary> + /// Gets extension nodes registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <param name="expectedNodeType"> + /// Expected node type. + /// </param> + /// <returns> + /// A list of nodes + /// </returns> + /// <remarks> + /// This method returns all nodes registered under the provided path. + /// It will throw a InvalidOperationException if the type of one of + /// the registered nodes is not assignable to the provided type. + /// </remarks> public ExtensionNodeList GetExtensionNodes (string path, Type expectedNodeType) { TreeNode node = GetNode (path); @@ -296,16 +444,47 @@ namespace Mono.Addins return list; } + /// <summary> + /// Gets extension objects registered for a type extension point. + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <returns> + /// A list of objects + /// </returns> public object[] GetExtensionObjects (Type instanceType) { return GetExtensionObjects (instanceType, true); } + /// <summary> + /// Gets extension objects registered for a type extension point. + /// </summary> + /// <returns> + /// A list of objects + /// </returns> + /// <remarks> + /// The type argument of this generic method is the type that defines + /// the extension point. + /// </remarks> public T[] GetExtensionObjects<T> () { return GetExtensionObjects<T> (true); } + /// <summary> + /// Gets extension objects registered for a type extension point. + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <param name="reuseCachedInstance"> + /// When set to True, it will return instances created in previous calls. + /// </param> + /// <returns> + /// A list of extension objects. + /// </returns> public object[] GetExtensionObjects (Type instanceType, bool reuseCachedInstance) { string path = AddinEngine.GetAutoTypeExtensionPoint (instanceType); @@ -314,6 +493,19 @@ namespace Mono.Addins return GetExtensionObjects (path, instanceType, reuseCachedInstance); } + /// <summary> + /// Gets extension objects registered for a type extension point. + /// </summary> + /// <param name="reuseCachedInstance"> + /// When set to True, it will return instances created in previous calls. + /// </param> + /// <returns> + /// A list of extension objects. + /// </returns> + /// <remarks> + /// The type argument of this generic method is the type that defines + /// the extension point. + /// </remarks> public T[] GetExtensionObjects<T> (bool reuseCachedInstance) { string path = AddinEngine.GetAutoTypeExtensionPoint (typeof(T)); @@ -322,26 +514,121 @@ namespace Mono.Addins return GetExtensionObjects<T> (path, reuseCachedInstance); } + /// <summary> + /// Gets extension objects registered in a path + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node. + /// </remarks> public object[] GetExtensionObjects (string path) { return GetExtensionObjects (path, typeof(object), true); } + /// <summary> + /// Gets extension objects registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <param name="reuseCachedInstance"> + /// When set to True, it will return instances created in previous calls. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node (or TypeExtensionNode.GetInstance() if + /// reuseCachedInstance is set to true) + /// </remarks> public object[] GetExtensionObjects (string path, bool reuseCachedInstance) { return GetExtensionObjects (path, typeof(object), reuseCachedInstance); } + /// <summary> + /// Gets extension objects registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <param name="arrayElementType"> + /// Type of the return array elements. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node. + /// + /// An InvalidOperationException exception is thrown if one of the found + /// objects is not a subclass of the provided type. + /// </remarks> public object[] GetExtensionObjects (string path, Type arrayElementType) { return GetExtensionObjects (path, arrayElementType, true); } + /// <summary> + /// Gets extension objects registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node. + /// + /// An InvalidOperationException exception is thrown if one of the found + /// objects is not a subclass of the provided type. + /// </remarks> public T[] GetExtensionObjects<T> (string path) { return GetExtensionObjects<T> (path, true); } + /// <summary> + /// Gets extension objects registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <param name="reuseCachedInstance"> + /// When set to True, it will return instances created in previous calls. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node (or TypeExtensionNode.GetInstance() if + /// reuseCachedInstance is set to true). + /// + /// An InvalidOperationException exception is thrown if one of the found + /// objects is not a subclass of the provided type. + /// </remarks> public T[] GetExtensionObjects<T> (string path, bool reuseCachedInstance) { ExtensionNode node = GetExtensionNode (path); @@ -350,6 +637,31 @@ namespace Mono.Addins return node.GetChildObjects<T> (reuseCachedInstance); } + /// <summary> + /// Gets extension objects registered in a path. + /// </summary> + /// <param name="path"> + /// An extension path. + /// </param> + /// <param name="arrayElementType"> + /// Type of the return array elements. + /// </param> + /// <param name="reuseCachedInstance"> + /// When set to True, it will return instances created in previous calls. + /// </param> + /// <returns> + /// An array of objects registered in the path. + /// </returns> + /// <remarks> + /// This method can only be used if all nodes in the provided extension path + /// are of type Mono.Addins.TypeExtensionNode. The returned array is composed + /// by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node (or TypeExtensionNode.GetInstance() if + /// reuseCachedInstance is set to true). + /// + /// An InvalidOperationException exception is thrown if one of the found + /// objects is not a subclass of the provided type. + /// </remarks> public object[] GetExtensionObjects (string path, Type arrayElementType, bool reuseCachedInstance) { ExtensionNode node = GetExtensionNode (path); @@ -358,6 +670,23 @@ namespace Mono.Addins return node.GetChildObjects (arrayElementType, reuseCachedInstance); } + /// <summary> + /// Register a listener of extension node changes. + /// </summary> + /// <param name="path"> + /// Path of the node. + /// </param> + /// <param name="handler"> + /// A handler method. + /// </param> + /// <remarks> + /// Hosts can call this method to be subscribed to an extension change + /// event for a specific path. The event will be fired once for every + /// individual node change. The event arguments include the change type + /// (Add or Remove) and the extension node added or removed. + /// + /// NOTE: The handler will be called for all nodes existing in the path at the moment of registration. + /// </remarks> public void AddExtensionNodeHandler (string path, ExtensionNodeEventHandler handler) { ExtensionNode node = GetExtensionNode (path); @@ -366,6 +695,18 @@ namespace Mono.Addins node.ExtensionNodeChanged += handler; } + /// <summary> + /// Unregister a listener of extension node changes. + /// </summary> + /// <param name="path"> + /// Path of the node. + /// </param> + /// <param name="handler"> + /// A handler method. + /// </param> + /// <remarks> + /// This method unregisters a delegate from the node change event of a path. + /// </remarks> public void RemoveExtensionNodeHandler (string path, ExtensionNodeEventHandler handler) { ExtensionNode node = GetExtensionNode (path); @@ -374,6 +715,23 @@ namespace Mono.Addins node.ExtensionNodeChanged -= handler; } + /// <summary> + /// Register a listener of extension node changes. + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <param name="handler"> + /// A handler method. + /// </param> + /// <remarks> + /// Hosts can call this method to be subscribed to an extension change + /// event for a specific type extension point. The event will be fired once for every + /// individual node change. The event arguments include the change type + /// (Add or Remove) and the extension node added or removed. + /// + /// NOTE: The handler will be called for all nodes existing in the path at the moment of registration. + /// </remarks> public void AddExtensionNodeHandler (Type instanceType, ExtensionNodeEventHandler handler) { string path = AddinEngine.GetAutoTypeExtensionPoint (instanceType); @@ -382,6 +740,15 @@ namespace Mono.Addins AddExtensionNodeHandler (path, handler); } + /// <summary> + /// Unregister a listener of extension node changes. + /// </summary> + /// <param name="instanceType"> + /// Type defining the extension point + /// </param> + /// <param name="handler"> + /// A handler method. + /// </param> public void RemoveExtensionNodeHandler (Type instanceType, ExtensionNodeEventHandler handler) { string path = AddinEngine.GetAutoTypeExtensionPoint (instanceType); @@ -845,6 +1212,9 @@ namespace Mono.Addins public delegate void ExtensionEventHandler (object sender, ExtensionEventArgs args); public delegate void ExtensionNodeEventHandler (object sender, ExtensionNodeEventArgs args); + /// <summary> + /// Arguments for extension events. + /// </summary> public class ExtensionEventArgs: EventArgs { string path; @@ -853,15 +1223,36 @@ namespace Mono.Addins { } + /// <summary> + /// Creates a new instance. + /// </summary> + /// <param name="path"> + /// Path of the extension node that has changed. + /// </param> public ExtensionEventArgs (string path) { this.path = path; } + /// <summary> + /// Path of the extension node that has changed. + /// </summary> public virtual string Path { get { return path; } } + /// <summary> + /// Checks if a path has changed. + /// </summary> + /// <param name="pathToCheck"> + /// An extension path. + /// </param> + /// <returns> + /// 'true' if the path is affected by the extension change event. + /// </returns> + /// <remarks> + /// Checks if the specified path or any of its children paths is affected by the extension change event. + /// </remarks> public bool PathChanged (string pathToCheck) { if (pathToCheck.EndsWith ("/")) @@ -871,29 +1262,53 @@ namespace Mono.Addins } } + /// <summary> + /// Arguments for extension node events. + /// </summary> public class ExtensionNodeEventArgs: ExtensionEventArgs { ExtensionNode node; ExtensionChange change; + /// <summary> + /// Creates a new instance + /// </summary> + /// <param name="change"> + /// Type of change. + /// </param> + /// <param name="node"> + /// Node that has been added or removed. + /// </param> public ExtensionNodeEventArgs (ExtensionChange change, ExtensionNode node) { this.node = node; this.change = change; } + /// <summary> + /// Path of the extension that changed. + /// </summary> public override string Path { get { return node.Path; } } + /// <summary> + /// Type of change. + /// </summary> public ExtensionChange Change { get { return change; } } + /// <summary> + /// Node that has been added or removed. + /// </summary> public ExtensionNode ExtensionNode { get { return node; } } + /// <summary> + /// Extension object that has been added or removed. + /// </summary> public object ExtensionObject { get { InstanceExtensionNode tnode = node as InstanceExtensionNode; @@ -904,9 +1319,19 @@ namespace Mono.Addins } } + /// <summary> + /// Type of change in an extension change event. + /// </summary> public enum ExtensionChange { + /// <summary> + /// An extension node has been added. + /// </summary> Add, + + /// <summary> + /// An extension node has been removed. + /// </summary> Remove } diff --git a/Mono.Addins/Mono.Addins/ExtensionNode.cs b/Mono.Addins/Mono.Addins/ExtensionNode.cs index a51fb2f..e93d1ed 100644 --- a/Mono.Addins/Mono.Addins/ExtensionNode.cs +++ b/Mono.Addins/Mono.Addins/ExtensionNode.cs @@ -36,6 +36,18 @@ using Mono.Addins.Description; namespace Mono.Addins { + /// <summary> + /// A node of the extension model. + /// </summary> + /// <remarks> + /// An extension node is an element registered by an add-in in an extension point. + /// A host can get nodes registered in an extension point using methods such as + /// AddinManager.GetExtensionNodes(string), which returns a collection of ExtensionNode objects. + /// + /// ExtensionNode will normally be used as a base class of more complex extension point types. + /// The most common subclass is Mono.Addins.TypeExtensionNode, which allows registering a class + /// implemented in an add-in. + /// </remarks> public class ExtensionNode { bool childrenLoaded; @@ -48,14 +60,33 @@ namespace Mono.Addins AddinEngine addinEngine; event ExtensionNodeEventHandler extensionNodeChanged; + /// <summary> + /// Identifier of the node. + /// </summary> + /// <remarks> + /// It is not mandatory to specify an 'id' for a node. When none is provided, + /// the add-in manager will automatically generate an unique id for the node. + /// The ExtensionNode.HasId property can be used to know if the 'id' has been + /// specified by the developer or not. + /// </remarks> public string Id { get { return treeNode != null ? treeNode.Id : string.Empty; } } + /// <summary> + /// Location of this node in the extension tree. + /// </summary> + /// <remarks> + /// The node path is composed by the path of the extension point where it is defined, + /// the identifiers of its parent nodes, and its own identifier. + /// </remarks> public string Path { get { return treeNode != null ? treeNode.GetPath () : string.Empty; } } + /// <summary> + /// Parent node of this node. + /// </summary> public ExtensionNode Parent { get { if (treeNode != null && treeNode.Parent != null) @@ -65,10 +96,22 @@ namespace Mono.Addins } } + /// <summary> + /// Extension context to which this node belongs + /// </summary> public ExtensionContext ExtensionContext { get { return treeNode.Context; } } + /// <summary> + /// Specifies whether the extension node has as an Id or not. + /// </summary> + /// <remarks> + /// It is not mandatory to specify an 'id' for a node. When none is provided, + /// the add-in manager will automatically generate an unique id for the node. + /// This property will return true if an 'id' was provided for the node, and + /// false if the id was assigned by the add-in manager. + /// </remarks> public bool HasId { get { return !Id.StartsWith (ExtensionTree.AutoIdPrefix); } } @@ -94,6 +137,12 @@ namespace Mono.Addins get { return treeNode; } } + /// <summary> + /// The add-in that registered this extension node. + /// </summary> + /// <remarks> + /// This property provides access to the resources and types of the add-in that created this extension node. + /// </remarks> public RuntimeAddin Addin { get { if (addin == null && addinId != null) { @@ -109,6 +158,12 @@ namespace Mono.Addins } } + /// <summary> + /// Notifies that a child node of this node has been added or removed. + /// </summary> + /// <remarks> + /// The first time the event is subscribed, the handler will be called for each existing node. + /// </remarks> public event ExtensionNodeEventHandler ExtensionNodeChanged { add { extensionNodeChanged += value; @@ -125,6 +180,9 @@ namespace Mono.Addins } } + /// <summary> + /// Child nodes of this extension node. + /// </summary> public ExtensionNodeList ChildNodes { get { if (childrenLoaded) @@ -166,31 +224,117 @@ namespace Mono.Addins } } + /// <summary> + /// Returns the child objects of a node. + /// </summary> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the + /// TypeExtensionNode.GetInstance() method for each node. + /// </remarks> public object[] GetChildObjects () { return GetChildObjects (typeof(object), true); } + /// <summary> + /// Returns the child objects of a node. + /// </summary> + /// <param name="reuseCachedInstance"> + /// True if the method can reuse instances created in previous calls. + /// </param> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node (or TypeExtensionNode.GetInstance() if reuseCachedInstance is set to true). + /// </remarks> public object[] GetChildObjects (bool reuseCachedInstance) { return GetChildObjects (typeof(object), reuseCachedInstance); } + /// <summary> + /// Returns the child objects of a node (with type check). + /// </summary> + /// <param name="arrayElementType"> + /// Type of the return array elements. + /// </param> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the + /// TypeExtensionNode.GetInstance(Type) method for each node. + /// + /// An InvalidOperationException exception is thrown if one of the found child objects is not a + /// subclass of the provided type. + /// </remarks> public object[] GetChildObjects (Type arrayElementType) { return GetChildObjects (arrayElementType, true); } + /// <summary> + /// Returns the child objects of a node (casting to the specified type) + /// </summary> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the + /// TypeExtensionNode.GetInstance() method for each node. + /// </remarks> public T[] GetChildObjects<T> () { return (T[]) GetChildObjectsInternal (typeof(T), true); } - + /// <summary> + /// Returns the child objects of a node (with type check). + /// </summary> + /// <param name="arrayElementType"> + /// Type of the return array elements. + /// </param> + /// <param name="reuseCachedInstance"> + /// True if the method can reuse instances created in previous calls. + /// </param> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the TypeExtensionNode.CreateInstance(Type) + /// method for each node (or TypeExtensionNode.GetInstance(Type) if reuseCachedInstance is set to true). + /// + /// An InvalidOperationException exception will be thrown if one of the found child objects is not a subclass + /// of the provided type. + /// </remarks> public object[] GetChildObjects (Type arrayElementType, bool reuseCachedInstance) { return (object[]) GetChildObjectsInternal (arrayElementType, reuseCachedInstance); } + /// <summary> + /// Returns the child objects of a node (casting to the specified type). + /// </summary> + /// <param name="reuseCachedInstance"> + /// True if the method can reuse instances created in previous calls. + /// </param> + /// <returns> + /// An array of child objects. + /// </returns> + /// <remarks> + /// This method only works if all children of this node are of type Mono.Addins.TypeExtensionNode. + /// The returned array is composed by all objects created by calling the TypeExtensionNode.CreateInstance() + /// method for each node (or TypeExtensionNode.GetInstance() if reuseCachedInstance is set to true). + /// </remarks> public T[] GetChildObjects<T> (bool reuseCachedInstance) { return (T[]) GetChildObjectsInternal (typeof(T), reuseCachedInstance); @@ -321,30 +465,47 @@ namespace Mono.Addins return changed; } - // Called when the add-in that defined this extension node is actually - // loaded in memory. + /// <summary> + /// Called when the add-in that defined this extension node is actually loaded in memory. + /// </summary> internal protected virtual void OnAddinLoaded () { } - // Called when the add-in that defined this extension node is being - // unloaded from memory. + /// <summary> + /// Called when the add-in that defined this extension node is being + /// unloaded from memory. + /// </summary> internal protected virtual void OnAddinUnloaded () { } - // Called when the children list of this node has changed. It may be due to add-ins - // being loaded/unloaded, or to conditions being changed. + /// <summary> + /// Called when the children list of this node has changed. It may be due to add-ins + /// being loaded/unloaded, or to conditions being changed. + /// </summary> protected virtual void OnChildrenChanged () { } + /// <summary> + /// Called when a child node is added + /// </summary> + /// <param name="node"> + /// Added node. + /// </param> protected virtual void OnChildNodeAdded (ExtensionNode node) { if (extensionNodeChanged != null) extensionNodeChanged (this, new ExtensionNodeEventArgs (ExtensionChange.Add, node)); } + /// <summary> + /// Called when a child node is removed + /// </summary> + /// <param name="node"> + /// Removed node. + /// </param> protected virtual void OnChildNodeRemoved (ExtensionNode node) { if (extensionNodeChanged != null) @@ -352,10 +513,19 @@ namespace Mono.Addins } } + /// <summary> + /// An extension node with custom metadata + /// </summary> + /// <remarks> + /// This is the default type for extension nodes bound to a custom extension attribute. + /// </remarks> public class ExtensionNode<T>: ExtensionNode where T:CustomExtensionAttribute { T data; + /// <summary> + /// The custom attribute containing the extension metadata + /// </summary> [NodeAttribute] public T Data { get { return data; } |