<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="/rss.xsl"?><rss version="2.0"><channel><title>MonoAddins Wiki Rss Feed</title><link>http://monoaddins.codeplex.com/wikipage</link><description>MonoAddins Wiki Rss Description</description><item><title>New Comment on "Extensions"</title><link>http://monoaddins.codeplex.com/wikipage?title=Extensions&amp;ANCHOR#C26804</link><description>It seems that &amp;#91;Mono.Addins.ExtensionNode&amp;#93; attribute should be &amp;#91;Mono.Addins.Extension&amp;#93; attribute.</description><author>jackjoy</author><pubDate>Fri, 08 Mar 2013 08:24:41 GMT</pubDate><guid isPermaLink="false">New Comment on "Extensions" 20130308082441A</guid></item><item><title>New Comment on "Architecture Overview"</title><link>http://monoaddins.codeplex.com/wikipage?title=Architecture Overview&amp;ANCHOR#C22942</link><description>It&amp;#39;s so nice&amp;#33;</description><author>yanweigps</author><pubDate>Fri, 16 Mar 2012 08:36:30 GMT</pubDate><guid isPermaLink="false">New Comment on "Architecture Overview" 20120316083630A</guid></item><item><title>New Comment on "Data-only Extension Points"</title><link>http://monoaddins.codeplex.com/wikipage?title=Data-only Extension Points&amp;ANCHOR#C21818</link><description>Fixed. Thanks&amp;#33;</description><author>slluis</author><pubDate>Tue, 06 Dec 2011 21:31:59 GMT</pubDate><guid isPermaLink="false">New Comment on "Data-only Extension Points" 20111206093159P</guid></item><item><title>Updated Wiki: Data-only Extension Points</title><link>http://monoaddins.codeplex.com/wikipage?title=Data-only Extension Points&amp;version=5</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Data-only Extension Points&lt;/h1&gt;
Extension data doesn&amp;#39;t always need to be type metadata. Mono.Addins also supports &lt;b&gt;data-only extension points&lt;/b&gt;. Applications are composed by code and by data. Type extensions points allow extending the code, data extension points allow extending data. For example, a word processor application could declare an extension point for registering document templates, or the main menu could be declared as an extensible data structure. Mono.Addins offers a common API and extension model for all kinds of extensions.&lt;br /&gt;&lt;br /&gt;Extension data can be specified using custom attributes, but it is also possible to use XML as explained in following chapters. For now, we&amp;#39;ll stick to custom attributes.&lt;br /&gt;
&lt;h2&gt;Declaring a Data-only Extension Point&lt;/h2&gt;
Here is an example of how to declare a data extension point:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:ExtensionPoint (&lt;span style="color:#A31515;"&gt;&amp;quot;/HelloWorld/WelcomeMessages&amp;quot;&lt;/span&gt;, ExtensionAttributeType=typeof(WelcomeMessageAttribute))]

&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; WelcomeMessageAttribute: Attribute
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; WelcomeMessageAttribute ([NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;)] &lt;span style="color:Blue;"&gt;string&lt;/span&gt; text)
	{
		Text = text;
	}

	[NodeAttribute]
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Text { &lt;span style="color:Blue;"&gt;get&lt;/span&gt;; &lt;span style="color:Blue;"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;[ExtensionPoint]&lt;/b&gt; attribute can be used at assembly level to declare a data-only extension point. The first parameter of the attribute is the &lt;b&gt;Path&lt;/b&gt; of the extension point. The path is like an identifier of the extension point. It starts with a slash and can contain several identifiers separated by slashes, like a file system path (although it is not bound to a real file system path, it is just an identifier).&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;ExtensionAttributeType&lt;/b&gt; property can be used to specify the custom attribute to be used to declare the extensions. The specified custom attribute must follow the rules explained in the &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Type%20Extension%20Metadata&amp;referringTitle=Data-only%20Extension%20Points"&gt;Type Extension Metadata&lt;/a&gt; section.&lt;br /&gt;
&lt;h2&gt;Declaring Data Extensions&lt;/h2&gt;
An add-in extending the above extension point would look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:Addin]
[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:AddinDependency (&lt;span style="color:#A31515;"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;, &amp;quot;1.0&amp;quot;)]

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:WelcomeMessage (&lt;span style="color:#A31515;"&gt;&amp;quot;Some message&amp;quot;&lt;/span&gt;)]
[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:WelcomeMessage (&lt;span style="color:#A31515;"&gt;&amp;quot;Another message&amp;quot;&lt;/span&gt;)]

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The above example declares two extensions of the &lt;b&gt;/HelloWorld/WelcomeMessages&lt;/b&gt; extension point.&lt;br /&gt;
&lt;h2&gt;Querying Data Extension Points&lt;/h2&gt;
The main application can query the data extension point using AddinManager.GetExtensionNodes():&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:AddinRoot (&lt;span style="color:#A31515;"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;, &amp;quot;1.0&amp;quot;)]

&lt;span style="color:Blue;"&gt;class&lt;/span&gt; MainClass
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Main ()
	{
		AddinManager.Initialize ();
		AddinManager.Registry.Update ();
		
		&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ExtensionNode&amp;lt;WelcomeMessageAttribute&amp;gt; node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/HelloWorld/WelcomeMessages&amp;quot;&lt;/span&gt;)) {
			Console.WriteLine (&lt;span style="color:#A31515;"&gt;&amp;quot;Message: &amp;quot;&lt;/span&gt; + node.Data.Text);
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When querying a data-only extension point bound to a custom extension attribute, the AddinManager.GetExtensionNodes() will return nodes of type &lt;b&gt;ExtensionNode&amp;lt;T&amp;gt;&lt;/b&gt;, where T is the type of the custom extension attribute. This class has a &lt;b&gt;Data&lt;/b&gt; property which contains the instance of the custom attribute with the extension data.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next topic:&lt;/b&gt; &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Data%20Files%20and%20Resources&amp;referringTitle=Data-only%20Extension%20Points"&gt;Data Files and Resources&lt;/a&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 06 Dec 2011 21:31:43 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Data-only Extension Points 20111206093143P</guid></item><item><title>Updated Wiki: Data-only Extension Points</title><link>http://monoaddins.codeplex.com/wikipage?title=Data-only Extension Points&amp;version=4</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Data-only Extension Points&lt;/h1&gt;
Extension data doesn&amp;#39;t always need to be type metadata. Mono.Addins also supports &lt;b&gt;data-only extension points&lt;/b&gt;. Applications are composed by code and by data. Type extensions points allow extending the code, data extension points allow extending data. For example, a word processor application could declare an extension point for registering document templates, or the main menu could be declared as an extensible data structure. Mono.Addins offers a common API and extension model for all kinds of extensions.&lt;br /&gt;&lt;br /&gt;Extension data can be specified using custom attributes, but it is also possible to use XML as explained in following chapters. For now, we&amp;#39;ll stick to custom attributes.&lt;br /&gt;
&lt;h2&gt;Declaring a Data-only Extension Point&lt;/h2&gt;
Here is an example of how to declare a data extension point:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:ExtensionPoint (&lt;span style="color:#A31515;"&gt;&amp;quot;/HelloWorld/WelcomeMessages&amp;quot;&lt;/span&gt;, ExtensionAttributeType=typeof(WelcomeMessageAttribute))]

&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; WelcomeMessageAttribute: Attribute
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; WelcomeMessageAttribute ([NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;Text&amp;quot;&lt;/span&gt;)] &lt;span style="color:Blue;"&gt;string&lt;/span&gt; text)
	{
		Text = text;
	}

	[NodeAttribute]
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Text { &lt;span style="color:Blue;"&gt;get&lt;/span&gt;; &lt;span style="color:Blue;"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;[ExtensionPoint]&lt;/b&gt; attribute can be used at assembly level to declare a data-only extension point. The first parameter of the attribute is the &lt;b&gt;Path&lt;/b&gt; of the extension point. The path is like an identifier of the extension point. It starts with a slash and can contain several identifiers separated by slashes, like a file system path (although it is not bound to a real file system path, it is just an identifier).&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;ExtensionAttributeType&lt;/b&gt; property can be used to specify the custom attribute to be used to declare the extensions. The specified custom attribute must follow the rules explained in the &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Type%20Extension%20Metadata&amp;referringTitle=Data-only%20Extension%20Points"&gt;Type Extension Metadata&lt;/a&gt; section.&lt;br /&gt;
&lt;h2&gt;Declaring Data Extensions&lt;/h2&gt;
An add-in extending the above extension point would look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:Addin]
[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:AddinDependency (&lt;span style="color:#A31515;"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;, &amp;quot;1.0&amp;quot;)]

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:WelcomeMessage (&lt;span style="color:#A31515;"&gt;&amp;quot;Some message&amp;quot;&lt;/span&gt;)]
[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:WelcomeMessage (&lt;span style="color:#A31515;"&gt;&amp;quot;Another message&amp;quot;&lt;/span&gt;)]

&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The above example declares two extensions of the &lt;b&gt;/HelloWorld/WelcomeMessages&lt;/b&gt; extension point.&lt;br /&gt;
&lt;h2&gt;Querying Data Extension Points&lt;/h2&gt;
The main application can query the data extension point using AddinManager.GetExtensionNodes():&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; System;
&lt;span style="color:Blue;"&gt;using&lt;/span&gt; Mono.Addins;

[&lt;span style="color:Blue;"&gt;assembly&lt;/span&gt;:AddinRoot (&lt;span style="color:#A31515;"&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt;, &amp;quot;1.0&amp;quot;)]

&lt;span style="color:Blue;"&gt;class&lt;/span&gt; MainClass
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Main ()
	{
		AddinManager.Initialize ();
		AddinManager.Registry.Update ();
		
		&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ExtensionNode&amp;lt;CommandAttribute&amp;gt; node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/HelloWorld/WelcomeMessages&amp;quot;&lt;/span&gt;)) {
			Console.WriteLine (&lt;span style="color:#A31515;"&gt;&amp;quot;Message: &amp;quot;&lt;/span&gt; + node.Data.Text);
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When querying a data-only extension point bound to a custom extension attribute, the AddinManager.GetExtensionNodes() will return nodes of type &lt;b&gt;ExtensionNode&amp;lt;T&amp;gt;&lt;/b&gt;, where T is the type of the custom extension attribute. This class has a &lt;b&gt;Data&lt;/b&gt; property which contains the instance of the custom attribute with the extension data.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next topic:&lt;/b&gt; &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Data%20Files%20and%20Resources&amp;referringTitle=Data-only%20Extension%20Points"&gt;Data Files and Resources&lt;/a&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 06 Dec 2011 21:30:56 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Data-only Extension Points 20111206093056P</guid></item><item><title>New Comment on "Data-only Extension Points"</title><link>http://monoaddins.codeplex.com/wikipage?title=Data-only Extension Points&amp;ANCHOR#C21803</link><description>Just some typoes&amp;#58;&amp;#10;&amp;#10;&amp;#91;assembly&amp;#58;ExtensionPoint &amp;#40;&amp;#34;&amp;#47;HelloWorld&amp;#47;WelcomeMessages&amp;#34;, ExtensionAttributeType&amp;#61;typeof&amp;#40;MessageAttribute&amp;#41;&amp;#41;&amp;#93;&amp;#10;must be&amp;#10;&amp;#91;assembly&amp;#58;ExtensionPoint &amp;#40;&amp;#34;&amp;#47;HelloWorld&amp;#47;WelcomeMessages&amp;#34;, ExtensionAttributeType&amp;#61;typeof&amp;#40;WelcomeMessageAttribute&amp;#41;&amp;#41;&amp;#93;&amp;#10;&amp;#10;foreach &amp;#40;ExtensionNode&amp;#60;CommandAttribute&amp;#62; node in AddinManager.GetExtensionNodes &amp;#40;&amp;#34;&amp;#47;HelloWorld&amp;#47;WelcomeMessages&amp;#34;&amp;#41;&amp;#41;&amp;#10;must be&amp;#10;foreach &amp;#40;ExtensionNode&amp;#60;WelcomeMessageAttribute&amp;#62; node in AddinManager.GetExtensionNodes &amp;#40;&amp;#34;&amp;#47;HelloWorld&amp;#47;WelcomeMessages&amp;#34;&amp;#41;&amp;#41;</description><author>AleckAgakhan</author><pubDate>Mon, 05 Dec 2011 23:24:36 GMT</pubDate><guid isPermaLink="false">New Comment on "Data-only Extension Points" 20111205112436P</guid></item><item><title>New Comment on "Architecture Overview"</title><link>http://monoaddins.codeplex.com/wikipage?title=Architecture Overview&amp;ANCHOR#C18936</link><description>The code in the first example &amp;#40;AddInRoot&amp;#41; is not consistent with the one in &amp;#34;Programming Guide&amp;#34; &amp;#47; &amp;#34;Extension Points and Extensions&amp;#34;. Shouldn&amp;#39;t the AddInRoot name be &amp;#34;HelloWorld&amp;#34; instead of &amp;#34;TextEditor&amp;#34;&amp;#63;</description><author>nelsonhf</author><pubDate>Wed, 16 Mar 2011 15:32:42 GMT</pubDate><guid isPermaLink="false">New Comment on "Architecture Overview" 20110316033242P</guid></item><item><title>Updated Wiki: Projects using Mono.Addins</title><link>http://monoaddins.codeplex.com/wikipage?title=Projects using Mono.Addins&amp;version=7</link><description>&lt;div class="wikidoc"&gt;This is a list of projects and applications that are using Mono.Addins.&lt;br /&gt;&lt;br /&gt;If you are using Mono.Addins and your project is not in the list, please add a comment to this page and I will add it.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://monodevelop.com" class="externalLink"&gt;MonoDevelop&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://banshee.fm" class="externalLink"&gt;Banshee&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://f-spot.org" class="externalLink"&gt;F-Spot&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://projects.gnome.org/tomboy" class="externalLink"&gt;Tomboy&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://do.davebsd.com" class="externalLink"&gt;GNOME Do&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://opensimulator.org" class="externalLink"&gt;OpenSimulator&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.fairmat.com" class="externalLink"&gt;Fairmat&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://live.gnome.org/gbrainy" class="externalLink"&gt;gbrainy&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mistelix.org" class="externalLink"&gt;Mistelix&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.lexim.com.au" class="externalLink"&gt;Convergence&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Wed, 09 Mar 2011 11:45:32 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Projects using Mono.Addins 20110309114532A</guid></item><item><title>Updated Wiki: Programming Guide</title><link>http://monoaddins.codeplex.com/wikipage?title=Programming Guide&amp;version=8</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Programming Guide&lt;/h1&gt;
This guide explains the basic concepts of Mono.Addins:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Extension%20Points%20and%20Extensions&amp;referringTitle=Programming%20Guide"&gt;Extension Points and Extensions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Querying%20Extension%20Points&amp;referringTitle=Programming%20Guide"&gt;Querying Extension Points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Type%20Extension%20Metadata&amp;referringTitle=Programming%20Guide"&gt;Type Extension Metadata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Data-only%20Extension%20Points&amp;referringTitle=Programming%20Guide"&gt;Data-only Extension Points&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Data%20Files%20and%20Resources&amp;referringTitle=Programming%20Guide"&gt;Data Files and Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=About%20Lazy%20Loading&amp;referringTitle=Programming%20Guide"&gt;About Lazy Loading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=The%20Add-in%20Registry&amp;referringTitle=Programming%20Guide"&gt;The Add-in Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Addin%20Discovery%20Basics&amp;referringTitle=Programming%20Guide"&gt;Addin Discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Creating%20and%20Managing%20Add-in%20Packages&amp;referringTitle=Programming%20Guide"&gt;Creating and Managing Add-in Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://monoaddins.codeplex.com/wikipage?title=Advanced%20Concepts&amp;referringTitle=Programming%20Guide"&gt;Advanced Concepts&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 22 Feb 2011 07:57:21 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Programming Guide 20110222075721A</guid></item><item><title>Updated Wiki: Creating and Managing Add-in Packages</title><link>http://monoaddins.codeplex.com/wikipage?title=Creating and Managing Add-in Packages&amp;version=5</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Creating and Managing Add-in Packages&lt;/h1&gt;
Mono.Addins follows the &lt;i&gt;xcopy&lt;/i&gt; model for managing add-ins: to install an add-in, all that needs to be done is to copy it to the application&amp;#39;s add-ins folder. However, applications may want to offer an user interface for managing add-ins, and even may need to provide an on-line repository from which users can browse and install add-ins. Mono.Addins provides an API and a command line tool which makes it easier to implement add-in management tools in applications.&lt;br /&gt;
&lt;h2&gt;The &lt;i&gt;mautil&lt;/i&gt; command line tool&lt;/h2&gt;
&lt;i&gt;mautil&lt;/i&gt; is a generic command line tool which can be used to manage add-ins of any Mono.Addins based application. It has commands for listing, installing and uninstalling add-ins, registering on-line repositories, and downloading add-ins from those repositories.&lt;br /&gt;&lt;br /&gt;For example, to list all add-ins installed for an application, the following command can be used:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;-p&lt;/b&gt; argument specifies the location of the application executable (the directory where the application .exe is located), and the &lt;b&gt;-reg&lt;/b&gt; argument specifies the location of the add-in registry for the application (the path provided when calling AddinManager.Initialize).&lt;br /&gt;
&lt;h2&gt;Creating add-in packages&lt;/h2&gt;
Add-ins may be composed by several files and assemblies, so in order to make it easier to share, download and install add-ins from on-line repositories add-ins must be packaged. An add-in package is basically a compressed archive (with .mpack extension) which contains all files of an add-in. Add-in packages can be created using the &lt;i&gt;mautil&lt;/i&gt; command tool. For example:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.dll &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This command will generate a file name SomeAddin.mpack which contains SomeAddin.dll and any other file imported by that add-in. This command can also be used to package add-ins based on manifests:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.addin &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice that only the main add-in file (either the dll or the manifest) has to be specified. It is important to properly declare assembly and file imports so that those are included in the package.&lt;br /&gt;
&lt;h2&gt;Creating an add-in repository&lt;/h2&gt;
An on-line repository of add-ins can be created with some simple steps:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Package and copy all add-ins you want to publish to a directory&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Run the following command (where /the/directory is the directory that contains the add-in packages). This command will generate some index files:&lt;/li&gt;&lt;/ul&gt;
   &lt;span class="codeInline"&gt; &amp;gt; mautil rep-build /the/directory &lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make all the files available in an http server&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Installing add-ins from a repository&lt;/h2&gt;
Before installing add-ins from a repository, the repository has to be registered. This can be done using the following command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg rep-add http://some.server/some/directory &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Available add-ins can be listed using the &amp;#39;list-av&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list-av &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once the repository is installed, add-ins can be installed using the &amp;#39;install&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg install SomeAddin,1.0 &lt;/span&gt;&lt;br /&gt;
&lt;h2&gt;Implementing application-specific add-in management tools&lt;/h2&gt;
Mono.Addins provides an add-in management API which can be easily integrated in applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupService&lt;/b&gt; class (in the Mono.Addins.Setup assembly) provides methods for installing and uninstalling add-ins, with support for dependency resolution.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.RepositoryRegistry&lt;/b&gt; class (available through the SetupService.Repositories property) allows registering on-line repositories, and listing available add-ins and add-in updates.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupTool&lt;/b&gt; class can be used to implement an application-specific command line tool for managing add-ins. This tool will behave like &lt;i&gt;mautil&lt;/i&gt;, but it will not be necessary to provide the application and registry paths, and it can be customized to provide application specific commands.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Gui&lt;/b&gt; assembly provides several classes which implement an add-in manager user interface for GTK# based applications.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 22 Feb 2011 07:56:12 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Creating and Managing Add-in Packages 20110222075612A</guid></item><item><title>Updated Wiki: Creating and Managing Add-in Packages</title><link>http://monoaddins.codeplex.com/wikipage?title=Creating and Managing Add-in Packages&amp;version=4</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Creating and Managing Add-in Packages&lt;/h1&gt;
Mono.Addins follows the &lt;i&gt;xcopy&lt;/i&gt; model for managing add-ins: to install an add-in, all that needs to be done is to copy it to the application&amp;#39;s add-ins folder. However, applications may want to offer an user interface for managing add-ins, and even may need to provide an on-line repository from which users can browse and install add-ins. Mono.Addins provides an API and a command line tool which makes it easier to implement add-in management tools in applications.&lt;br /&gt;
&lt;h2&gt;The &lt;i&gt;mautil&lt;/i&gt; command line tool&lt;/h2&gt;
&lt;i&gt;mautil&lt;/i&gt; is a generic command line tool which can be used to manage add-ins of any Mono.Addins based application. It has commands for listing, installing and uninstalling add-ins, registering on-line repositories, and downloading add-ins from those repositories.&lt;br /&gt;&lt;br /&gt;For example, to list all add-ins installed for an application, the following command can be used:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;-p&lt;/b&gt; argument specifies the location of the application executable (the directory where the application .exe is located), and the &lt;b&gt;-reg&lt;/b&gt; argument specifies the location of the add-in registry for the application (the path provided when calling AddinManager.Initialize).&lt;br /&gt;
&lt;h2&gt;Creating add-in packages&lt;/h2&gt;
Add-ins may be composed by several files and assemblies, so in order to make it easier to share, download and install add-ins from on-line repositories add-ins must be packaged. An add-in package is basically a compressed archive (with .mpack extension) which contains all files of an add-in. Add-in packages can be created using the &lt;i&gt;mautil&lt;/i&gt; command tool. For example:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.dll &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This command will generate a file name SomeAddin.mpack which contains SomeAddin.dll and any other file imported by that add-in. This command can also be used to package add-ins based on manifests:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.addin &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice that only the main add-in file (either the dll or the manifest) has to be specified. It is important to properly declare assembly and file imports so that those are included in the package.&lt;br /&gt;
&lt;h2&gt;Creating an add-in repository&lt;/h2&gt;
An on-line repository of add-ins can be created with some simple steps:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Package and copy all add-ins you want to publish to a directory&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Run the following command (where /the/directory is the directory that contains the add-in packages). This command will generate some index files:&lt;/li&gt;&lt;/ul&gt;
   &lt;span class="codeInline"&gt; &amp;gt; mautil rep-build /the/directory &lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make all the files available in an http server&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Installing add-ins from a repository&lt;/h2&gt;
Before installing add-ins from a repository, the repository has to be registered. This can be done using the following command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg rep-add http://some.server/some/directory &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Available add-ins can be listed using the &amp;#39;list-av&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list-av &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once the repository is installed, add-ins can be installed using the &amp;#39;install&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg install SomeAddin,1.0 &lt;/span&gt;&lt;br /&gt;
&lt;h2&gt;Implementing application-specific add-in management tools&lt;/h2&gt;
Mono.Addins provides an add-in management API which can be easily integrated in applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupService&lt;/b&gt; class (in the Mono.Addins.Setup assembly) provides methods for installing and uninstalling add-ins, with support for dependency resolution.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.RepositoryRegistry&lt;/b&gt; class (available in SetupService.Repositories) allows registering on-line repositories, and listing available add-ins and add-in updates.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupTool&lt;/b&gt; class can be used to implement an application-specific command line tool for managing add-ins. This tool will behave like &lt;i&gt;mautil&lt;/i&gt;, but it will not be necessary to provide the application and registry paths, and it can be customized to provide application specific commands.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Gui&lt;/b&gt; assembly provides several classes which implement an add-in manager user interface for GTK# based applications.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 22 Feb 2011 07:54:55 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Creating and Managing Add-in Packages 20110222075455A</guid></item><item><title>Updated Wiki: Creating and Managing Add-in Packages</title><link>http://monoaddins.codeplex.com/wikipage?title=Creating and Managing Add-in Packages&amp;version=3</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Creating and Managing Add-in Packages&lt;/h1&gt;
Mono.Addins follows the &lt;i&gt;xcopy&lt;/i&gt; model for managing add-ins: to install an add-in, all that needs to be done is to copy it to the application&amp;#39;s add-ins folder. However, applications may want to offer an user interface for managing add-ins, and even may need to provide an on-line repository from which users can browse and install add-ins. Mono.Addins provides an API and a command line tool which makes it easier to implement add-in management tools in applications.&lt;br /&gt;
&lt;h2&gt;The &lt;i&gt;mautil&lt;/i&gt; command line tool&lt;/h2&gt;
&lt;i&gt;mautil&lt;/i&gt; is a generic command line tool which can be used to manage add-ins of any Mono.Addins based application. It has commands for listing, installing and uninstalling add-ins, registering on-line repositories, and downloading add-ins from those repositories.&lt;br /&gt;&lt;br /&gt;For example, to list all add-ins installed for an application, the following command can be used:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;-p&lt;/b&gt; argument specifies the location of the application executable (the directory where the application .exe is located), and the &lt;b&gt;-reg&lt;/b&gt; argument specifies the location of the add-in registry for the application (the path provided when calling AddinManager.Initialize).&lt;br /&gt;
&lt;h2&gt;Creating add-in packages&lt;/h2&gt;
Add-ins may be composed by several files and assemblies, so in order to make it easier to share, download and install add-ins from on-line repositories add-ins must be packaged. An add-in package is basically a compressed archive (with .mpack extension) which contains all files of an add-in. Add-in packages can be created using the &lt;i&gt;mautil&lt;/i&gt; command tool. For example:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.dll &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This command will generate a file name SomeAddin.mpack which contains SomeAddin.dll and any other file imported by that add-in. This command can also be used to package add-ins based on manifests:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.addin &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice that only the main add-in file (either the dll or the manifest) has to be specified. It is important to properly declare assembly and file imports so that those are included in the package.&lt;br /&gt;
&lt;h2&gt;Creating an add-in repository&lt;/h2&gt;
An on-line repository of add-ins can be created with some simple steps:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Package and copy all add-ins you want to publish to a directory&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Run the following command (where /the/directory is the directory that contains the add-in packages). This command will generate some index files:&lt;/li&gt;&lt;/ul&gt;
   &lt;span class="codeInline"&gt; &amp;gt; mautil rep-build /the/directory &lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make all the files available in an http server&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Installing add-ins from a repository&lt;/h2&gt;
Before installing add-ins from a repository, the repository has to be registered. This can be done using the following command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg rep-add http://some.server/some/directory &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Available add-ins can be listed using the &amp;#39;list-av&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list-av &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once the repository is installed, add-ins can be installed using the &amp;#39;install&amp;#39; command:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg install SomeAddin,1.0 &lt;/span&gt;&lt;br /&gt;
&lt;h2&gt;Implementing application-specific add-in management tools&lt;/h2&gt;
Mono.Addins provides an add-in management API which can be easily integrated in applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupService&lt;/b&gt; class (in the Mono.Addins.Setup assembly) provides methods for installing and uninstalling add-ins, with support for dependency resolution.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.RepositoryRegistry&lt;/b&gt; class (available in SetupService.Repositories) allows registering on-line repositories, and listing available add-ins and add-in updates.&lt;/li&gt;
&lt;li&gt;The *Mono.Addins.Setup.SetupTool&amp;quot; class can be used to implement an application-specific command line tool for managing add-ins. This tool will behave like &lt;i&gt;mautil&lt;/i&gt;, but it will not be necessary to provide the application and registry paths, and it can be customized to provide application specific commands.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Gui&lt;/b&gt; assembly provides several classes which implement an add-in manager user interface for GTK# based applications.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Tue, 22 Feb 2011 07:54:15 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Creating and Managing Add-in Packages 20110222075415A</guid></item><item><title>Updated Wiki: Creating and Managing Add-in Packages</title><link>http://monoaddins.codeplex.com/wikipage?title=Creating and Managing Add-in Packages&amp;version=2</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Creating and Managing Add-in Packages&lt;/h1&gt;
Mono.Addins follows the &lt;i&gt;xcopy&lt;/i&gt; model for managing add-ins: to install an add-in, all that needs to be done is to copy it to the application&amp;#39;s add-ins folder. However, applications may want to offer an user interface for managing add-ins, and even may need to provide an on-line repository from which users can browse and install add-ins. Mono.Addins provides an API and a command line tool which makes it easier to implement add-in management tools in applications.&lt;br /&gt;
&lt;h2&gt;The &lt;i&gt;mautil&lt;/i&gt; command line tool&lt;/h2&gt;
&lt;i&gt;mautil&lt;/i&gt; is a generic command line tool which can be used to manage add-ins of any Mono.Addins based application. It has commands for listing, installing and uninstalling add-ins, registering on-line repositories, and downloading add-ins from those repositories.&lt;br /&gt;&lt;br /&gt;For example, to list all add-ins installed for an application, the following command can be used:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;-p&lt;/b&gt; argument specifies the location of the application executable (the directory where the application .exe is located), and the &lt;b&gt;-reg&lt;/b&gt; argument specifies the location of the add-in registry for the application (the path provided when calling AddinManager.Initialize).&lt;br /&gt;
&lt;h2&gt;Creating add-in packages&lt;/h2&gt;
Add-ins may be composed by several files and assemblies, so in order to make it easier to share, download and install add-ins from on-line repositories add-ins must be packaged. An add-in package is basically a compressed archive (with .mpack extension) which contains all files of an add-in. Add-in packages can be created using the &lt;i&gt;mautil&lt;/i&gt; command tool. For example:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.dll &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This command will generate a file name SomeAddin.mpack which contains SomeAddin.dll and any other file imported by that add-in. This command can also be used to package add-ins based on manifests:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.addin &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice that only the main add-in file (either the dll or the manifest) have to be specified. It is important to properly declare assembly and file imports so that those are included in the package.&lt;br /&gt;
&lt;h2&gt;Creating an add-in repository&lt;/h2&gt;
An on-line repository of add-ins can be created with some simple steps:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Package and copy all add-ins you want to publish to a directory&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Run the following command (where /the/directory is the directory that contains the add-in packages (.mpack files). This command will generate some index files:&lt;/li&gt;&lt;/ul&gt;
   &lt;span class="codeInline"&gt; &amp;gt; mautil rep-build /the/directory &lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make all the files available in an http server&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Implementing application-specific add-in management tools&lt;/h2&gt;
Mono.Addins provides an add-in management API which can be easily integrated in applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupService&lt;/b&gt; class (in the Mono.Addins.Setup assembly) provides methods for installing and uninstalling add-ins, with support for dependency resolution.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.RepositoryRegistry&lt;/b&gt; class (available in SetupService.Repositories) allows registering on-line repositories, and listing available add-ins and add-in updates.&lt;/li&gt;
&lt;li&gt;The *Mono.Addins.Setup.SetupTool&amp;quot; class can be used to implement an application-specific command line tool for managing add-ins. This tool will behave like &lt;i&gt;mautil&lt;/i&gt;, but it will not be necessary to provide the application and registry paths, and it can be customized to provide application specific commands.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Gui&lt;/b&gt; assembly provides several classes which implement an add-in manager user interface for GTK# based applications.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 20:36:36 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Creating and Managing Add-in Packages 20110221083636P</guid></item><item><title>Updated Wiki: Creating and Managing Add-in Packages</title><link>http://monoaddins.codeplex.com/wikipage?title=Creating and Managing Add-in Packages&amp;version=1</link><description>&lt;div class="wikidoc"&gt;Mono.Addins follows the &lt;i&gt;xcopy&lt;/i&gt; model for managing add-ins: to install an add-in, all that needs to be done is to copy it to the application&amp;#39;s add-ins folder. However, applications may want to offer an user interface for managing add-ins, and even may need to provide an on-line repository from which users can browse and install add-ins. Mono.Addins provides an API and a command line tool which makes it easier to implement add-in management tools in applications.&lt;br /&gt;
&lt;h2&gt;The &lt;i&gt;mautil&lt;/i&gt; command line tool&lt;/h2&gt;
&lt;i&gt;mautil&lt;/i&gt; is a generic command line tool which can be used to manage add-ins of any Mono.Addins based application. It has commands for listing, installing and uninstalling add-ins, registering on-line repositories, and downloading add-ins from those repositories.&lt;br /&gt;&lt;br /&gt;For example, to list all add-ins installed for an application, the following command can be used:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil -p /my/app -reg /my/app/reg list &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;-p&lt;/b&gt; argument specifies the location of the application executable (the directory where the application .exe is located), and the &lt;b&gt;-reg&lt;/b&gt; argument specifies the location of the add-in registry for the application (the path provided when calling AddinManager.Initialize).&lt;br /&gt;
&lt;h2&gt;Creating add-in packages&lt;/h2&gt;
Add-ins may be composed by several files and assemblies, so in order to make it easier to share, download and install add-ins from on-line repositories add-ins must be packaged. An add-in package is basically a compressed archive (with .mpack extension) which contains all files of an add-in. Add-in packages can be created using the &lt;i&gt;mautil&lt;/i&gt; command tool. For example:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.dll &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This command will generate a file name SomeAddin.mpack which contains SomeAddin.dll and any other file imported by that add-in. This command can also be used to package add-ins based on manifests:&lt;br /&gt;&lt;br /&gt;&lt;span class="codeInline"&gt; &amp;gt; mautil pack SomeAddin.addin &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Notice that only the main add-in file (either the dll or the manifest) have to be specified. It is important to properly declare assembly and file imports so that those are included in the package.&lt;br /&gt;
&lt;h2&gt;Creating an add-in repository&lt;/h2&gt;
An on-line repository of add-ins can be created with some simple steps:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Package and copy all add-ins you want to publish to a directory&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;Run the following command (where /the/directory is the directory that contains the add-in packages (.mpack files). This command will generate some index files:&lt;/li&gt;&lt;/ul&gt;
   &lt;span class="codeInline"&gt; &amp;gt; mautil rep-build /the/directory &lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make all the files available in an http server&lt;/li&gt;&lt;/ul&gt;

&lt;h2&gt;Implementing application-specific add-in management tools&lt;/h2&gt;
Mono.Addins provides an add-in management API which can be easily integrated in applications:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.SetupService&lt;/b&gt; class (in the Mono.Addins.Setup assembly) provides methods for installing and uninstalling add-ins, with support for dependency resolution.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Setup.RepositoryRegistry&lt;/b&gt; class (available in SetupService.Repositories) allows registering on-line repositories, and listing available add-ins and add-in updates.&lt;/li&gt;
&lt;li&gt;The *Mono.Addins.Setup.SetupTool&amp;quot; class can be used to implement an application-specific command line tool for managing add-ins. This tool will behave like &lt;i&gt;mautil&lt;/i&gt;, but it will not be necessary to provide the application and registry paths, and it can be customized to provide application specific commands.&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;Mono.Addins.Gui&lt;/b&gt; assembly provides several classes which implement an add-in manager user interface for GTK# based applications.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 20:36:15 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Creating and Managing Add-in Packages 20110221083615P</guid></item><item><title>Updated Wiki: Custom Extension Node Types</title><link>http://monoaddins.codeplex.com/wikipage?title=Custom Extension Node Types&amp;version=4</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Custom Extension Node Types&lt;/h1&gt;
Every extension point has to declare the type of extension node that it accepts. Add-ins can register new extension nodes to that extension point. At run-time, extension nodes are represented by instances of the class &lt;b&gt;Mono.Addins.ExtensionNode&lt;/b&gt; or instances of a subclass of it. Hosts can query extension points and get instances of ExtensionNode to extract whatever extension information is needed from them.&lt;br /&gt;&lt;br /&gt;Mono.Addins provides the class TypeExtensionNode, a type of extension node which covers a very common extension scenario: the host defines an interface (or type), and the add-in has to implement it. At run-time TypeExtensionNode represents a type registered by an add-in, and a host can create instances out of it.&lt;br /&gt;&lt;br /&gt;TypeExtensionNode may be enough for simple applications, but more complex applications will need to define new extension node types, so more complex extension information can be declared in extension points. Also, extension nodes don&amp;#39;t always need to represent type implementations. In those cases, a host will need to implement custom extension node types.&lt;br /&gt;&lt;a name="Custom extension node implementation"&gt;&lt;/a&gt;
&lt;h2&gt;Custom extension node implementation&lt;/h2&gt;
Creating extension node types is very simple. Let&amp;#39;s see one example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader(Addin.GetResource (resource))) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This extension node type is used in the Text Editor example to register file templates. When creating a new file, the user can choose a file template, so the new file will include the content provided by the template.&lt;br /&gt;&lt;br /&gt;This class does several interesing things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;It inherits from Mono.Addins.ExtensionNode. All extension node types must be a subclass of this type.&lt;/li&gt;
&lt;li&gt;It declares a field named &lt;b&gt;resource&lt;/b&gt; and marks it with the &lt;b&gt;NodeAttribute&lt;/b&gt; custom attribute. When creating a node instance, all fields marked with this attribute will be initialized using attribute values taken from the node. &lt;/li&gt;
&lt;li&gt;It implements a &lt;b&gt;GetContent&lt;/b&gt; method which gets the content of a template using Addin.GetResource. The &lt;b&gt;Addin&lt;/b&gt; property is declared in ExtensionNode and provides access to add-in resources and types.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;This node type would be able to represent nodes registered in an extension like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;...&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;README&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;readme-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;ChangeLog&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;changelog-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When calling AddinManager.GetExtensionNodes(), the add-in engine will read all registered elements and will create the corresponding ExtensionNode subclass instance for each of them. It will also transfer attribute values to fields marked with [NodeAttribute].&lt;br /&gt;&lt;br /&gt;Extension nodes are not just data containers, but they can also implement some logic. In this example the host application doesn&amp;#39;t need to know where does a FileTemplateNode get the template content from. This logic is hidden in FileTemplateNode. FileTemplateNode happens to get the content from a resource, but it might allow getting it from other places in the future.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;[NodeAttribute]&lt;/b&gt; attribute can be applied to fields and properties. It has several properties which allow defining and documenting the behavior of the attribute:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt; Property &lt;/th&gt;&lt;th&gt; Description &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Name &lt;/td&gt;&lt;td&gt; Name of the attribute, to be used when it is different from the name of the field or property &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Required &lt;/td&gt;&lt;td&gt; When set to &amp;#39;true&amp;#39; specifies that it is mandatory to specify a value for the attribute &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Description &lt;/td&gt;&lt;td&gt; Description of the purpose of the attribute &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Localizable &lt;/td&gt;&lt;td&gt; When set to &amp;#39;true&amp;#39;, the value of the field or property is expected to be a string id which will be localized by the add-in engine &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; ContentType &lt;/td&gt;&lt;td&gt; Allows specifying the type of the content of a string attribute. This is for documentation purposes only.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;a name="Extension node deserialization"&gt;&lt;/a&gt;
&lt;h2&gt;Extension node deserialization&lt;/h2&gt;
The &lt;b&gt;[NodeAttribute]&lt;/b&gt; custom attribute can be used to specify fields and properties that have to be initialized from node attributes. By default, a field is will get its value from an attribute with the same name, although it is possible to specify a different name by setting the &lt;b&gt;NodeAttribute.Name&lt;/b&gt; property. NodeAttribute also has a &lt;b&gt;Required&lt;/b&gt; property for specifying if an attribute is mandatory or not. So for example the &amp;#39;&amp;#39;resource&amp;#39;&amp;#39; filed might be declared like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Green;"&gt;// Will match elements like &amp;lt;FileTemplate resource-name=&amp;quot;blah&amp;quot; /&amp;gt;&lt;/span&gt;
	&lt;span style="color:Green;"&gt;// The true parameter specifies that the attribute is required&lt;/span&gt;
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ExtensionNode subclasses can also override the virtual method &lt;b&gt;Read (NodeElement elem)&lt;/b&gt; to take control on the process of loading a ExtensionNode instance out of an extension node. If the Read method is overriden (and if it doesn&amp;#39;t call the base class) [NodeAttribute] attributes will be ignored.&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;

	&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
	{
		&lt;span style="color:Green;"&gt;// This is equivalent to the previous example, but more&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// eficient since reflection is not involved here&lt;/span&gt;
		resource = elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;);
	}
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice the [NodeAttribute] attribute declaration applied to the class. When using custom deserialization, [NodeAttribute] can be applied to the class (or to a field) to declare the extension node attributes. This information however is only used for documentation purposes, and the add-in engine will not use it to do any kind of check. All checks must be done by the Read method override.&lt;br /&gt;&lt;a name="Getting add-in types, files and resources"&gt;&lt;/a&gt;
&lt;h2&gt;Getting add-in types, files and resources&lt;/h2&gt;
As seen in the previous examples, the object returned by the ExtensionNode.Addin property can be used to get information from the add-in that created a node. It is a protected property, and it is intended to be used by ExtensionNode subclasses to get whatever content is needed. There are three methods which can be used to get such content:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;GetResource (string name)&lt;/b&gt;: returns a resource embedded in any of the assemblies included in the add-in.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetType (string name)&lt;/b&gt;: returns a type implemented in any of the assemblies included in the add-in, or in any of the add-ins on which this add-in depends.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetFilePath (string name)&lt;/b&gt;: Returns a path to a file which has been deployed together with the add-in.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Working with add-in files"&gt;&lt;/a&gt;
&lt;h2&gt;Working with add-in files&lt;/h2&gt;
It is possible to distribute files together with the add-in, and access those files from extension nodes. To distribute a file with an add-in, the file has to be declared in the &lt;b&gt;Runtime&lt;/b&gt; section. For example, let&amp;#39;s say we improve FileTemplateNode, so it can get the template not only from resources, but also from files distributed together with the add-in. An add-in declaration might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;namespace&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;id&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;Xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;assembly&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor.Xml.dll&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;file&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		...
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;SomeTemplate&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;fileName&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		...
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The FileTemplateNode class would need to handle the new &lt;b&gt;fileName&lt;/b&gt; attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; fileName;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			StreamReader sr;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				&lt;span style="color:Green;"&gt;// GetFilePath returns the full path to the add-in file&lt;/span&gt;
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetFilePath (fileName));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;

			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="The private data directory"&gt;&lt;/a&gt;
&lt;h2&gt;The private data directory&lt;/h2&gt;
Every add-in has a private directory which can be used to store add-in specific files created at run time. This directory is created the first time that access to it is requested, and will be deleted when the add-in is uninstalled.&lt;br /&gt;&lt;br /&gt;For example, let&amp;#39;s say we want to support compressed file templates in FileTemplateNode. The GetContent method would need to uncompress the file before reading it, and it should be done only once. The implementation might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
{
	StreamReader sr;
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		
		&lt;span style="color:Green;"&gt;// Get the full path to the add-in file&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; filePath = Addin.GetFilePath (fileName);
		
		&lt;span style="color:Green;"&gt;// If it is a gzipped file, it needs additional processing&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (filePath.EndsWith (&lt;span style="color:#A31515;"&gt;&amp;quot;.gz&amp;quot;&lt;/span&gt;)) {
			
			&lt;span style="color:Green;"&gt;// The file will be unzipped in an add-in specific folder&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;string&lt;/span&gt; unzippedFile = Path.Combine (Addin.PrivateDataPath, Path.GetFileNameWithoutExtension (filePath));
			
			&lt;span style="color:Green;"&gt;// Unzip only once&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (!File.Exists (unzippedFile))
				UnzipFileTo (filePath, unzippedFile);
			
			filePath = unzippedFile;
		}
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (filePath);
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;
	&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Default node name and description"&gt;&lt;/a&gt;
&lt;h2&gt;Default node name and description&lt;/h2&gt;
When an extension point does not provide a name for a node type, a default node name will be used. This default node name is the name of the class that implements it.&lt;br /&gt;&lt;br /&gt;It is also possible to provide a custom default name, and also a description, to be used in those cases. This information can be provided using the [ExtensionNode] attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;FileTemplate&amp;quot;&lt;/span&gt;, &lt;span style="color:#A31515;"&gt;&amp;quot;A file template the user can choose when creating a new file&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: Mono.Addins.ExtensionNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Handling children"&gt;&lt;/a&gt;
&lt;h2&gt;Handling children&lt;/h2&gt;
The property &lt;b&gt;ExtensionNode.ChildNodes&lt;/b&gt; returns a list of children of a node. ExtensionNode implementations can query this list in order to build objects which are composed by several nodes.&lt;br /&gt;&lt;br /&gt;For example, the TextEditor.SubmenuNode extension node, which represents an extensible submenu of the main menu, might be implemented like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	[NodeAttribute]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; label;
	
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; Gtk.MenuItem GetMenuItem ()
	{
		&lt;span style="color:Green;"&gt;// Create the menu item&lt;/span&gt;
		Gtk.MenuItem it = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.MenuItem (label);
		Gtk.Menu submenu = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.Menu ();

		&lt;span style="color:Green;"&gt;// Iterate through all children, and add a menu item for each of them&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (MenuNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ChildNodes)
			submenu.Insert (node.GetMenuItem (), -1);
		it.Submenu = submenu;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; it;
	}
}

&lt;span style="color:Green;"&gt;// Abstract class to be subclassed by any kind of node that&lt;/span&gt;
&lt;span style="color:Green;"&gt;// can generate a menu item.&lt;/span&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuNode: ExtensionNode
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; Gtk.MenuItem GetMenuItem ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;ChildNodes&lt;/b&gt; list may dynamically change while the application is running as a result of add-ins being enabled/disabled, or if the status of some conditions change. There are some overridable methods which are called when this happen: &lt;b&gt;OnChildNodeAdded&lt;/b&gt;, &lt;b&gt;OnChildNodeRemoved&lt;/b&gt; and a more generic &lt;b&gt;OnChildrenChanged&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;[ExtensionNodeChild]&lt;/b&gt; attribute allows declaring the type of the child nodes of a node:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;Menu&amp;quot;&lt;/span&gt;)]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuItemNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuSeparatorNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SubmenuNode))]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	...
} 

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuSeparator&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuSeparatorNode: MenuNode
{
	...
}

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuItem&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuItemNode: MenuNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice that it is allowed to use recursive node type references.&lt;br /&gt;&lt;a name="Localizable extension nodes"&gt;&lt;/a&gt;
&lt;h2&gt;Localizable extension nodes&lt;/h2&gt;
Some extension node types may have attributes that need to be localizable. For example, the label of a menu item, or (in the text editor example) the name of a file template. Any text attribute can be made localizable by setting the &lt;b&gt;Localizable&lt;/b&gt; property of NodeAttribute to &amp;#39;&amp;#39;true&amp;#39;&amp;#39;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		[NodeAttribute (Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; {
				&lt;span style="color:Green;"&gt;// &amp;#39;name&amp;#39; will be already localized here&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; 
			}
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When an attribute is declared localizable like this, the add-in engine will use the add-in localizer bound to the extension node to get a translation of the string, and will assign the translated string to the field.&lt;br /&gt;&lt;br /&gt;When using custom deserialization, the &lt;b&gt;RuntimeAddin.Localizer&lt;/b&gt; property can be used to get the localizer bound to the add-in declaring the extension node. The following example would be equivalent to the previous one:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;, Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
		{
			name = Addin.Localizer.GetString (elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;));
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The [NodeAttribute] attribute declaration is used in this case only for documentation purposes.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Localization%20of%20Add-ins&amp;referringTitle=Custom%20Extension%20Node%20Types"&gt;Localization of Add-ins&lt;/a&gt; for more information about creating localizable add-ins.&lt;br /&gt;&lt;a name="Controlling add-in loading"&gt;&lt;/a&gt;
&lt;h2&gt;Controlling add-in loading&lt;/h2&gt;
Mono.Addins supports lazy loading of add-ins. Add-ins are never explicitly loaded, but they are loaded only when resources or types from that add-in are required. It is important to take this behavior into account when designing extension nodes. Let&amp;#39;s see for example the implementation of the an extension node for registering toolbar buttons:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; ToolButtonNode: ExtensionNode
	{
		&lt;span style="color:Green;"&gt;// Name of the icon&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; icon;
		
		&lt;span style="color:Green;"&gt;// Name of the class that implements the command&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// to run when clicking the button&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; commandType;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; Gtk.ToolItem GetToolItem ()
		{
			&lt;span style="color:Green;"&gt;// Create the button and subscribe the clicked event&lt;/span&gt;
			Gtk.ToolButton but = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.ToolButton (icon);
			but.Clicked += OnClicked;
			&lt;span style="color:Blue;"&gt;return&lt;/span&gt; but;
		}
		
		&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnClicked (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, EventArgs a)
		{
			&lt;span style="color:Green;"&gt;// Run the command when clicking the button&lt;/span&gt;
			ICommand command = (ICommand) Addin.CreateInstance (commandType);
			command.Run ();
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;commandType&lt;/b&gt; attribute will have the name of a type which is supposed to implement ICommand. When the button is clicked, the event handler creates an instance of the command and executes it. The call to Addin.CreateInstance () will force the loading of the add-in that registered that node, since CreateInstance needs to load the type of the command. However, this will only happen when the button is clicked. That is, it would be possible to create a complete toolbar out of add-in buttons without having to load the add-ins that define them.&lt;br /&gt;&lt;br /&gt;An extension node may need to know when the add-in that defined it has been loaded or unloaded, since it may need to do some initialization or cleanup work. ExtensionNode has two virtual methods &lt;b&gt;OnAddinLoaded&lt;/b&gt; and &lt;b&gt;OnAddinUnloaded&lt;/b&gt; which can be used for this purpose.&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 19:27:15 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Custom Extension Node Types 20110221072715P</guid></item><item><title>Updated Wiki: Custom Extension Node Types</title><link>http://monoaddins.codeplex.com/wikipage?title=Custom Extension Node Types&amp;version=3</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Custom Extension Node Types&lt;/h1&gt;
Every extension point has to declare the type of extension node that it accepts. Add-ins can register new extension nodes to that extension point. At run-time, extension nodes are represented by instances of the class &lt;b&gt;Mono.Addins.ExtensionNode&lt;/b&gt; or instances of a subclass of it. Hosts can query extension points and get instances of ExtensionNode to extract whatever extension information is needed from them.&lt;br /&gt;&lt;br /&gt;Mono.Addins provides the class TypeExtensionNode, a type of extension node which covers a very common extension scenario: the host defines an interface (or type), and the add-in has to implement it. At run-time TypeExtensionNode represents a type registered by an add-in, and a host can create instances out of it.&lt;br /&gt;&lt;br /&gt;TypeExtensionNode may be enough for simple applications, but more complex applications will need to define new extension node types, so more complex extension information can be declared in extension points. Also, extension nodes don&amp;#39;t always need to represent type implementations. In those cases, a host will need to implement custom extension node types.&lt;br /&gt;&lt;a name="Custom extension node implementation"&gt;&lt;/a&gt;
&lt;h2&gt;Custom extension node implementation&lt;/h2&gt;
Creating extension node types is very simple. Let&amp;#39;s see one example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader(Addin.GetResource (resource))) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This extension node type is used in the Text Editor example to register file templates. When creating a new file, the user can choose a file template, so the new file will include the content provided by the template.&lt;br /&gt;&lt;br /&gt;This class does several interesing things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;It inherits from Mono.Addins.ExtensionNode. All extension node types must be a subclass of this type.&lt;/li&gt;
&lt;li&gt;It declares a field named &lt;b&gt;resource&lt;/b&gt; and marks it with the &lt;b&gt;NodeAttribute&lt;/b&gt; custom attribute. When creating a node instance, all fields marked with this attribute will be initialized using attribute values taken from the node. &lt;/li&gt;
&lt;li&gt;It implements a &lt;b&gt;GetContent&lt;/b&gt; method which gets the content of a template using Addin.GetResource. The &lt;b&gt;Addin&lt;/b&gt; property is declared in ExtensionNode and provides access to add-in resources and types.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;This node type would be able to represent nodes registered in an extension like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;...&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;README&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;readme-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;ChangeLog&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;changelog-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When calling AddinManager.GetExtensionNodes(), the add-in engine will read all registered elements and will create the corresponding ExtensionNode subclass instance for each of them. It will also transfer attribute values to fields marked with [NodeAttribute].&lt;br /&gt;&lt;br /&gt;Extension nodes are not just data containers, but they can also implement some logic. In this example the host application doesn&amp;#39;t need to know where does a FileTemplateNode get the template content from. This logic is hidden in FileTemplateNode. FileTemplateNode happens to get the content from a resource, but it might allow getting it from other places in the future.&lt;br /&gt;&lt;br /&gt;The [NodeAttribute] attribute has several properties:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt; Property &lt;/th&gt;&lt;th&gt; Description &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Name &lt;/td&gt;&lt;td&gt; Name of the attribute, to be used when it is different from the name of the field or property &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Required &lt;/td&gt;&lt;td&gt; When set to &amp;#39;true&amp;#39; specifies that it is mandatory to specify a value for the attribute &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Description &lt;/td&gt;&lt;td&gt; Description of the purpose of the attribute &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; Localizable &lt;/td&gt;&lt;td&gt; When set to &amp;#39;true&amp;#39;, the value of the field or property is expected to be a string id which will be localized by the add-in engine &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; ContentType &lt;/td&gt;&lt;td&gt; Allows specifying the type of the content of a string attribute. This is for documentation purposes only.&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;a name="Extension node deserialization"&gt;&lt;/a&gt;
&lt;h2&gt;Extension node deserialization&lt;/h2&gt;
The &lt;b&gt;[NodeAttribute]&lt;/b&gt; custom attribute can be used to specify fields that have to be initialized from node attributes. By default, a field is will get its value from an attribute with the same name, although it is possible to specify a different name by setting the &lt;b&gt;NodeAttribute.Name&lt;/b&gt; property. NodeAttribute also has a &lt;b&gt;Required&lt;/b&gt; property for specifying if an attribute is mandatory or not. So for example the &amp;#39;&amp;#39;resource&amp;#39;&amp;#39; filed might be declared like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Green;"&gt;// Will match elements like &amp;lt;FileTemplate resource-name=&amp;quot;blah&amp;quot; /&amp;gt;&lt;/span&gt;
	&lt;span style="color:Green;"&gt;// The true parameter specifies that the attribute is required&lt;/span&gt;
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ExtensionNode subclasses can also override the virtual method &lt;b&gt;Read (NodeElement elem)&lt;/b&gt; to take control on the process of loading a ExtensionNode instance out of an extension node. If the Read method is overriden (and if it doesn&amp;#39;t call the base class) [NodeAttribute] attributes will be ignored.&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;

	&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
	{
		&lt;span style="color:Green;"&gt;// This is equivalent to the previous example, but more&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// eficient since reflection is not involved here&lt;/span&gt;
		resource = elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;);
	}
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice the [NodeAttribute] attribute declaration applied to the class. When using custom deserialization, [NodeAttribute] can be applied to the class (or to a field) to declare the extension node attributes. This information however is only used for documentation purposes, and the add-in engine will not use it to do any kind of check. All checks must be done by the Read method override.&lt;br /&gt;&lt;a name="Getting add-in types, files and resources"&gt;&lt;/a&gt;
&lt;h2&gt;Getting add-in types, files and resources&lt;/h2&gt;
As seen in the previous examples, the object returned by the ExtensionNode.Addin property can be used to get information from the add-in that created a node. It is a protected property, and it is intended to be used by ExtensionNode subclasses to get whatever content is needed. There are three methods which can be used to get such content:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;GetResource (string name)&lt;/b&gt;: returns a resource embedded in any of the assemblies included in the add-in.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetType (string name)&lt;/b&gt;: returns a type implemented in any of the assemblies included in the add-in, or in any of the add-ins on which this add-in depends.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetFilePath (string name)&lt;/b&gt;: Returns a path to a file which has been deployed together with the add-in.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Working with add-in files"&gt;&lt;/a&gt;
&lt;h2&gt;Working with add-in files&lt;/h2&gt;
It is possible to distribute files together with the add-in, and access those files from extension nodes. To distribute a file with an add-in, the file has to be declared in the &lt;b&gt;Runtime&lt;/b&gt; section. For example, let&amp;#39;s say we improve FileTemplateNode, so it can get the template not only from resources, but also from files distributed together with the add-in. An add-in declaration might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;namespace&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;id&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;Xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;assembly&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor.Xml.dll&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;file&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		...
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;SomeTemplate&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;fileName&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		...
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The FileTemplateNode class would need to handle the new &lt;b&gt;fileName&lt;/b&gt; attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; fileName;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			StreamReader sr;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				&lt;span style="color:Green;"&gt;// GetFilePath returns the full path to the add-in file&lt;/span&gt;
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetFilePath (fileName));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;

			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="The private data directory"&gt;&lt;/a&gt;
&lt;h2&gt;The private data directory&lt;/h2&gt;
Every add-in has a private directory which can be used to store add-in specific files created at run time. This directory is created the first time that access to it is requested, and will be deleted when the add-in is uninstalled.&lt;br /&gt;&lt;br /&gt;For example, let&amp;#39;s say we want to support compressed file templates in FileTemplateNode. The GetContent method would need to uncompress the file before reading it, and it should be done only once. The implementation might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
{
	StreamReader sr;
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		
		&lt;span style="color:Green;"&gt;// Get the full path to the add-in file&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; filePath = Addin.GetFilePath (fileName);
		
		&lt;span style="color:Green;"&gt;// If it is a gzipped file, it needs additional processing&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (filePath.EndsWith (&lt;span style="color:#A31515;"&gt;&amp;quot;.gz&amp;quot;&lt;/span&gt;)) {
			
			&lt;span style="color:Green;"&gt;// The file will be unzipped in an add-in specific folder&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;string&lt;/span&gt; unzippedFile = Path.Combine (Addin.PrivateDataPath, Path.GetFileNameWithoutExtension (filePath));
			
			&lt;span style="color:Green;"&gt;// Unzip only once&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (!File.Exists (unzippedFile))
				UnzipFileTo (filePath, unzippedFile);
			
			filePath = unzippedFile;
		}
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (filePath);
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;
	&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Default node name and description"&gt;&lt;/a&gt;
&lt;h2&gt;Default node name and description&lt;/h2&gt;
When an extension point does not provide a name for a node type, a default node name will be used. This default node name is the name of the class that implements it.&lt;br /&gt;&lt;br /&gt;It is also possible to provide a custom default name, and also a description, to be used in those cases. This information can be provided using the [ExtensionNode] attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;FileTemplate&amp;quot;&lt;/span&gt;, &lt;span style="color:#A31515;"&gt;&amp;quot;A file template the user can choose when creating a new file&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: Mono.Addins.ExtensionNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Handling children"&gt;&lt;/a&gt;
&lt;h2&gt;Handling children&lt;/h2&gt;
The property &lt;b&gt;ExtensionNode.ChildNodes&lt;/b&gt; returns a list of children of a node. ExtensionNode implementations can query this list in order to build objects which are composed by several nodes.&lt;br /&gt;&lt;br /&gt;For example, the TextEditor.SubmenuNode extension node, which represents an extensible submenu of the main menu, might be implemented like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	[NodeAttribute]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; label;
	
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; Gtk.MenuItem GetMenuItem ()
	{
		&lt;span style="color:Green;"&gt;// Create the menu item&lt;/span&gt;
		Gtk.MenuItem it = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.MenuItem (label);
		Gtk.Menu submenu = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.Menu ();

		&lt;span style="color:Green;"&gt;// Iterate through all children, and add a menu item for each of them&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (MenuNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ChildNodes)
			submenu.Insert (node.GetMenuItem (), -1);
		it.Submenu = submenu;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; it;
	}
}

&lt;span style="color:Green;"&gt;// Abstract class to be subclassed by any kind of node that&lt;/span&gt;
&lt;span style="color:Green;"&gt;// can generate a menu item.&lt;/span&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuNode: ExtensionNode
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; Gtk.MenuItem GetMenuItem ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;ChildNodes&lt;/b&gt; list may dynamically change while the application is running as a result of add-ins being enabled/disabled, or if the status of some conditions change. There are some overridable methods which are called when this happen: &lt;b&gt;OnChildNodeAdded&lt;/b&gt;, &lt;b&gt;OnChildNodeRemoved&lt;/b&gt; and a more generic &lt;b&gt;OnChildrenChanged&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;[ExtensionNodeChild]&lt;/b&gt; attribute allows declaring the type of the child nodes of a node:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;Menu&amp;quot;&lt;/span&gt;)]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuItemNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuSeparatorNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SubmenuNode))]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	...
} 

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuSeparator&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuSeparatorNode: MenuNode
{
	...
}

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuItem&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuItemNode: MenuNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice that it is allowed to use recursive node type references.&lt;br /&gt;&lt;a name="Localizable extension nodes"&gt;&lt;/a&gt;
&lt;h2&gt;Localizable extension nodes&lt;/h2&gt;
Some extension node types may have attributes that need to be localizable. For example, the label of a menu item, or (in the text editor example) the name of a file template. Any text attribute can be made localizable by setting the &lt;b&gt;Localizable&lt;/b&gt; property of NodeAttribute to &amp;#39;&amp;#39;true&amp;#39;&amp;#39;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		[NodeAttribute (Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; {
				&lt;span style="color:Green;"&gt;// &amp;#39;name&amp;#39; will be already localized here&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; 
			}
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When an attribute is declared localizable like this, the add-in engine will use the add-in localizer bound to the extension node to get a translation of the string, and will assign the translated string to the field.&lt;br /&gt;&lt;br /&gt;When using custom deserialization, the &lt;b&gt;RuntimeAddin.Localizer&lt;/b&gt; property can be used to get the localizer bound to the add-in declaring the extension node. The following example would be equivalent to the previous one:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;, Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
		{
			name = Addin.Localizer.GetString (elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;));
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The [NodeAttribute] attribute declaration is used in this case only for documentation purposes.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Localization%20of%20Add-ins&amp;referringTitle=Custom%20Extension%20Node%20Types"&gt;Localization of Add-ins&lt;/a&gt; for more information about creating localizable add-ins.&lt;br /&gt;&lt;a name="Controlling add-in loading"&gt;&lt;/a&gt;
&lt;h2&gt;Controlling add-in loading&lt;/h2&gt;
Mono.Addins supports lazy loading of add-ins. Add-ins are never explicitly loaded, but they are loaded only when resources or types from that add-in are required. It is important to take this behavior into account when designing extension nodes. Let&amp;#39;s see for example the implementation of the an extension node for registering toolbar buttons:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; ToolButtonNode: ExtensionNode
	{
		&lt;span style="color:Green;"&gt;// Name of the icon&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; icon;
		
		&lt;span style="color:Green;"&gt;// Name of the class that implements the command&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// to run when clicking the button&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; commandType;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; Gtk.ToolItem GetToolItem ()
		{
			&lt;span style="color:Green;"&gt;// Create the button and subscribe the clicked event&lt;/span&gt;
			Gtk.ToolButton but = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.ToolButton (icon);
			but.Clicked += OnClicked;
			&lt;span style="color:Blue;"&gt;return&lt;/span&gt; but;
		}
		
		&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnClicked (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, EventArgs a)
		{
			&lt;span style="color:Green;"&gt;// Run the command when clicking the button&lt;/span&gt;
			ICommand command = (ICommand) Addin.CreateInstance (commandType);
			command.Run ();
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;commandType&lt;/b&gt; attribute will have the name of a type which is supposed to implement ICommand. When the button is clicked, the event handler creates an instance of the command and executes it. The call to Addin.CreateInstance () will force the loading of the add-in that registered that node, since CreateInstance needs to load the type of the command. However, this will only happen when the button is clicked. That is, it would be possible to create a complete toolbar out of add-in buttons without having to load the add-ins that define them.&lt;br /&gt;&lt;br /&gt;An extension node may need to know when the add-in that defined it has been loaded or unloaded, since it may need to do some initialization or cleanup work. ExtensionNode has two virtual methods &lt;b&gt;OnAddinLoaded&lt;/b&gt; and &lt;b&gt;OnAddinUnloaded&lt;/b&gt; which can be used for this purpose.&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 19:22:08 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Custom Extension Node Types 20110221072208P</guid></item><item><title>Updated Wiki: Custom Extension Node Types</title><link>http://monoaddins.codeplex.com/wikipage?title=Custom Extension Node Types&amp;version=2</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Custom Extension Node Types&lt;/h1&gt;
Every extension point has to declare the type of extension node that it accepts. Add-ins can register new extension nodes to that extension point. At run-time, extension nodes are represented by instances of the class &lt;b&gt;Mono.Addins.ExtensionNode&lt;/b&gt; or instances of a subclass of it. Hosts can query extension points and get instances of ExtensionNode to extract whatever extension information is needed from them.&lt;br /&gt;&lt;br /&gt;Mono.Addins provides the class TypeExtensionNode, a type of extension node which covers a very common extension scenario: the host defines an interface (or type), and the add-in has to implement it. At run-time TypeExtensionNode represents a type registered by an add-in, and a host can create instances out of it.&lt;br /&gt;&lt;br /&gt;TypeExtensionNode may be enough for simple applications, but more complex applications will need to define new extension node types, so more complex extension information can be declared in extension points. Also, extension nodes don&amp;#39;t always need to represent type implementations. In those cases, a host will need to implement custom extension node types.&lt;br /&gt;&lt;a name="Custom extension node implementation"&gt;&lt;/a&gt;
&lt;h2&gt;Custom extension node implementation&lt;/h2&gt;
Creating extension node types is very simple. Let&amp;#39;s see one example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader(Addin.GetResource (resource))) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This extension node type is used in the Text Editor example to register file templates. When creating a new file, the user can choose a file template, so the new file will include the content provided by the template.&lt;br /&gt;&lt;br /&gt;This class does several interesing things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;It inherits from Mono.Addins.ExtensionNode. All extension node types must be a subclass of this type.&lt;/li&gt;
&lt;li&gt;It declares a field named &lt;b&gt;resource&lt;/b&gt; and marks it with the &lt;b&gt;NodeAttribute&lt;/b&gt; custom attribute. When creating a node instance, all fields marked with this attribute will be initialized using attribute values taken from the node. &lt;/li&gt;
&lt;li&gt;It implements a &lt;b&gt;GetContent&lt;/b&gt; method which gets the content of a template using Addin.GetResource. The &lt;b&gt;Addin&lt;/b&gt; property is declared in ExtensionNode and provides access to add-in resources and types.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;This node type would be able to represent nodes registered in an extension like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;...&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;README&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;readme-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;ChangeLog&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;resource&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;changelog-template.txt&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When calling AddinManager.GetExtensionNodes(), the add-in engine will read all registered elements and will create the corresponding ExtensionNode subclass instance for each of them. It will also transfer attribute values to fields marked with [NodeAttribute].&lt;br /&gt;&lt;br /&gt;Extension nodes are not just data containers, but they can also implement some logic. In this example the host application doesn&amp;#39;t need to know where does a FileTemplateNode get the template content from. This logic is hidden in FileTemplateNode. FileTemplateNode happens to get the content from a resource, but it might allow getting it from other places in the future.&lt;br /&gt;&lt;a name="Extension node deserialization"&gt;&lt;/a&gt;
&lt;h2&gt;Extension node deserialization&lt;/h2&gt;
The &lt;b&gt;[NodeAttribute]&lt;/b&gt; custom attribute can be used to specify fields that have to be initialized from node attributes. By default, a field is will get its value from an attribute with the same name, although it is possible to specify a different name by setting the &lt;b&gt;NodeAttribute.Name&lt;/b&gt; property. NodeAttribute also has a &lt;b&gt;Required&lt;/b&gt; property for specifying if an attribute is mandatory or not. So for example the &amp;#39;&amp;#39;resource&amp;#39;&amp;#39; filed might be declared like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Green;"&gt;// Will match elements like &amp;lt;FileTemplate resource-name=&amp;quot;blah&amp;quot; /&amp;gt;&lt;/span&gt;
	&lt;span style="color:Green;"&gt;// The true parameter specifies that the attribute is required&lt;/span&gt;
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;ExtensionNode subclasses can also override the virtual method &lt;b&gt;Read (NodeElement elem)&lt;/b&gt; to take control on the process of loading a ExtensionNode instance out of an extension node. If the Read method is overriden (and if it doesn&amp;#39;t call the base class) [NodeAttribute] attributes will be ignored.&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;, &lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
{
	...
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;

	&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
	{
		&lt;span style="color:Green;"&gt;// This is equivalent to the previous example, but more&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// eficient since reflection is not involved here&lt;/span&gt;
		resource = elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;resource-name&amp;quot;&lt;/span&gt;);
	}
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice the [NodeAttribute] attribute declaration applied to the class. When using custom deserialization, [NodeAttribute] can be applied to the class (or to a field) to declare the extension node attributes. This information however is only used for documentation purposes, and the add-in engine will not use it to do any kind of check. All checks must be done by the Read method override.&lt;br /&gt;&lt;a name="Getting add-in types, files and resources"&gt;&lt;/a&gt;
&lt;h2&gt;Getting add-in types, files and resources&lt;/h2&gt;
As seen in the previous examples, the object returned by the ExtensionNode.Addin property can be used to get information from the add-in that created a node. It is a protected property, and it is intended to be used by ExtensionNode subclasses to get whatever content is needed. There are three methods which can be used to get such content:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;GetResource (string name)&lt;/b&gt;: returns a resource embedded in any of the assemblies included in the add-in.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetType (string name)&lt;/b&gt;: returns a type implemented in any of the assemblies included in the add-in, or in any of the add-ins on which this add-in depends.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GetFilePath (string name)&lt;/b&gt;: Returns a path to a file which has been deployed together with the add-in.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Working with add-in files"&gt;&lt;/a&gt;
&lt;h2&gt;Working with add-in files&lt;/h2&gt;
It is possible to distribute files together with the add-in, and access those files from extension nodes. To distribute a file with an add-in, the file has to be declared in the &lt;b&gt;Runtime&lt;/b&gt; section. For example, let&amp;#39;s say we improve FileTemplateNode, so it can get the template not only from resources, but also from files distributed together with the add-in. An add-in declaration might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt; &lt;span style="color:Red;"&gt;namespace&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;id&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;Xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;assembly&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;TextEditor.Xml.dll&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Import&lt;/span&gt; &lt;span style="color:Red;"&gt;file&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Runtime&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
	&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt; &lt;span style="color:Red;"&gt;path&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;/TextEditor/Templates&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
		...
		&lt;span style="color:Blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#A31515;"&gt;FileTemplate&lt;/span&gt; &lt;span style="color:Red;"&gt;name&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;SomeTemplate&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Red;"&gt;fileName&lt;/span&gt;&lt;span style="color:Blue;"&gt;=&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:Blue;"&gt;someTemplate.xml&lt;/span&gt;&lt;span style="color:Black;"&gt;&amp;quot;&lt;/span&gt; &lt;span style="color:Blue;"&gt;/&amp;gt;&lt;/span&gt;
		...
	&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Extension&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
	...
&lt;span style="color:Blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#A31515;"&gt;Addin&lt;/span&gt;&lt;span style="color:Blue;"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The FileTemplateNode class would need to handle the new &lt;b&gt;fileName&lt;/b&gt; attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; resource;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; fileName;
		
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; { &lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; }
		}
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
		{
			StreamReader sr;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;)
				&lt;span style="color:Green;"&gt;// GetFilePath returns the full path to the add-in file&lt;/span&gt;
				sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetFilePath (fileName));
			&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;

			&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
			}
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="The private data directory"&gt;&lt;/a&gt;
&lt;h2&gt;The private data directory&lt;/h2&gt;
Every add-in has a private directory which can be used to store add-in specific files created at run time. This directory is created the first time that access to it is requested, and will be deleted when the add-in is uninstalled.&lt;br /&gt;&lt;br /&gt;For example, let&amp;#39;s say we want to support compressed file templates in FileTemplateNode. The GetContent method would need to uncompress the file before reading it, and it should be done only once. The implementation might look like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;virtual&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; GetContent ()
{
	StreamReader sr;
	&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (resource != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (Addin.GetResource (resource));
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt; &lt;span style="color:Blue;"&gt;if&lt;/span&gt; (fileName != &lt;span style="color:Blue;"&gt;null&lt;/span&gt;) {
		
		&lt;span style="color:Green;"&gt;// Get the full path to the add-in file&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; filePath = Addin.GetFilePath (fileName);
		
		&lt;span style="color:Green;"&gt;// If it is a gzipped file, it needs additional processing&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (filePath.EndsWith (&lt;span style="color:#A31515;"&gt;&amp;quot;.gz&amp;quot;&lt;/span&gt;)) {
			
			&lt;span style="color:Green;"&gt;// The file will be unzipped in an add-in specific folder&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;string&lt;/span&gt; unzippedFile = Path.Combine (Addin.PrivateDataPath, Path.GetFileNameWithoutExtension (filePath));
			
			&lt;span style="color:Green;"&gt;// Unzip only once&lt;/span&gt;
			&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (!File.Exists (unzippedFile))
				UnzipFileTo (filePath, unzippedFile);
			
			filePath = unzippedFile;
		}
		sr = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; StreamReader (filePath);
	}
	&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; &lt;span style="color:Blue;"&gt;null&lt;/span&gt;;
	&lt;span style="color:Blue;"&gt;using&lt;/span&gt; (sr) {
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; sr.ReadToEnd (); 
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Default node name and description"&gt;&lt;/a&gt;
&lt;h2&gt;Default node name and description&lt;/h2&gt;
When an extension point does not provide a name for a node type, a default node name will be used. This default node name is the name of the class that implements it.&lt;br /&gt;&lt;br /&gt;It is also possible to provide a custom default name, and also a description, to be used in those cases. This information can be provided using the [ExtensionNode] attribute:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;FileTemplate&amp;quot;&lt;/span&gt;, &lt;span style="color:#A31515;"&gt;&amp;quot;A file template the user can choose when creating a new file&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: Mono.Addins.ExtensionNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Handling children"&gt;&lt;/a&gt;
&lt;h2&gt;Handling children&lt;/h2&gt;
The property &lt;b&gt;ExtensionNode.ChildNodes&lt;/b&gt; returns a list of children of a node. ExtensionNode implementations can query this list in order to build objects which are composed by several nodes.&lt;br /&gt;&lt;br /&gt;For example, the TextEditor.SubmenuNode extension node, which represents an extensible submenu of the main menu, might be implemented like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	[NodeAttribute]
	&lt;span style="color:Blue;"&gt;string&lt;/span&gt; label;
	
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; Gtk.MenuItem GetMenuItem ()
	{
		&lt;span style="color:Green;"&gt;// Create the menu item&lt;/span&gt;
		Gtk.MenuItem it = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.MenuItem (label);
		Gtk.Menu submenu = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.Menu ();

		&lt;span style="color:Green;"&gt;// Iterate through all children, and add a menu item for each of them&lt;/span&gt;
		&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (MenuNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ChildNodes)
			submenu.Insert (node.GetMenuItem (), -1);
		it.Submenu = submenu;
		&lt;span style="color:Blue;"&gt;return&lt;/span&gt; it;
	}
}

&lt;span style="color:Green;"&gt;// Abstract class to be subclassed by any kind of node that&lt;/span&gt;
&lt;span style="color:Green;"&gt;// can generate a menu item.&lt;/span&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuNode: ExtensionNode
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;abstract&lt;/span&gt; Gtk.MenuItem GetMenuItem ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;ChildNodes&lt;/b&gt; list may dynamically change while the application is running as a result of add-ins being enabled/disabled, or if the status of some conditions change. There are some overridable methods which are called when this happen: &lt;b&gt;OnChildNodeAdded&lt;/b&gt;, &lt;b&gt;OnChildNodeRemoved&lt;/b&gt; and a more generic &lt;b&gt;OnChildrenChanged&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;b&gt;[ExtensionNodeChild]&lt;/b&gt; attribute allows declaring the type of the child nodes of a node:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;Menu&amp;quot;&lt;/span&gt;)]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuItemNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(MenuSeparatorNode))]
[ExtensionNodeChild (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(SubmenuNode))]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; SubmenuNode: MenuNode
{
	...
} 

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuSeparator&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuSeparatorNode: MenuNode
{
	...
}

[ExtensionNode (&lt;span style="color:#A31515;"&gt;&amp;quot;MenuItem&amp;quot;&lt;/span&gt;)]
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; MenuItemNode: MenuNode
{
	...
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Notice that it is allowed to use recursive node type references.&lt;br /&gt;&lt;a name="Localizable extension nodes"&gt;&lt;/a&gt;
&lt;h2&gt;Localizable extension nodes&lt;/h2&gt;
Some extension node types may have attributes that need to be localizable. For example, the label of a menu item, or (in the text editor example) the name of a file template. Any text attribute can be made localizable by setting the &lt;b&gt;Localizable&lt;/b&gt; property of NodeAttribute to &amp;#39;&amp;#39;true&amp;#39;&amp;#39;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		[NodeAttribute (Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;string&lt;/span&gt; Name {
			&lt;span style="color:Blue;"&gt;get&lt;/span&gt; {
				&lt;span style="color:Green;"&gt;// &amp;#39;name&amp;#39; will be already localized here&lt;/span&gt;
				&lt;span style="color:Blue;"&gt;return&lt;/span&gt; name != &lt;span style="color:Blue;"&gt;null&lt;/span&gt; ? name : Id; 
			}
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;When an attribute is declared localizable like this, the add-in engine will use the add-in localizer bound to the extension node to get a translation of the string, and will assign the translated string to the field.&lt;br /&gt;&lt;br /&gt;When using custom deserialization, the &lt;b&gt;RuntimeAddin.Localizer&lt;/b&gt; property can be used to get the localizer bound to the add-in declaring the extension node. The following example would be equivalent to the previous one:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	[NodeAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;, Localizable=&lt;span style="color:Blue;"&gt;true&lt;/span&gt;)]
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; FileTemplateNode: ExtensionNode
	{
		...
		
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; name;
		
		&lt;span style="color:Blue;"&gt;protected&lt;/span&gt; &lt;span style="color:Blue;"&gt;override&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Read (NodeElement elem)
		{
			name = Addin.Localizer.GetString (elem.GetAttribute (&lt;span style="color:#A31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;));
		}

		...
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The [NodeAttribute] attribute declaration is used in this case only for documentation purposes.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Localization%20of%20Add-ins&amp;referringTitle=Custom%20Extension%20Node%20Types"&gt;Localization of Add-ins&lt;/a&gt; for more information about creating localizable add-ins.&lt;br /&gt;&lt;a name="Controlling add-in loading"&gt;&lt;/a&gt;
&lt;h2&gt;Controlling add-in loading&lt;/h2&gt;
Mono.Addins supports lazy loading of add-ins. Add-ins are never explicitly loaded, but they are loaded only when resources or types from that add-in are required. It is important to take this behavior into account when designing extension nodes. Let&amp;#39;s see for example the implementation of the an extension node for registering toolbar buttons:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;namespace&lt;/span&gt; TextEditor
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; ToolButtonNode: ExtensionNode
	{
		&lt;span style="color:Green;"&gt;// Name of the icon&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; icon;
		
		&lt;span style="color:Green;"&gt;// Name of the class that implements the command&lt;/span&gt;
		&lt;span style="color:Green;"&gt;// to run when clicking the button&lt;/span&gt;
		[NodeAttribute]
		&lt;span style="color:Blue;"&gt;string&lt;/span&gt; commandType;
		
		&lt;span style="color:Blue;"&gt;public&lt;/span&gt; Gtk.ToolItem GetToolItem ()
		{
			&lt;span style="color:Green;"&gt;// Create the button and subscribe the clicked event&lt;/span&gt;
			Gtk.ToolButton but = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; Gtk.ToolButton (icon);
			but.Clicked += OnClicked;
			&lt;span style="color:Blue;"&gt;return&lt;/span&gt; but;
		}
		
		&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnClicked (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, EventArgs a)
		{
			&lt;span style="color:Green;"&gt;// Run the command when clicking the button&lt;/span&gt;
			ICommand command = (ICommand) Addin.CreateInstance (commandType);
			command.Run ();
		}
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The &lt;b&gt;commandType&lt;/b&gt; attribute will have the name of a type which is supposed to implement ICommand. When the button is clicked, the event handler creates an instance of the command and executes it. The call to Addin.CreateInstance () will force the loading of the add-in that registered that node, since CreateInstance needs to load the type of the command. However, this will only happen when the button is clicked. That is, it would be possible to create a complete toolbar out of add-in buttons without having to load the add-ins that define them.&lt;br /&gt;&lt;br /&gt;An extension node may need to know when the add-in that defined it has been loaded or unloaded, since it may need to do some initialization or cleanup work. ExtensionNode has two virtual methods &lt;b&gt;OnAddinLoaded&lt;/b&gt; and &lt;b&gt;OnAddinUnloaded&lt;/b&gt; which can be used for this purpose.&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 19:04:04 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Custom Extension Node Types 20110221070404P</guid></item><item><title>Updated Wiki: Handling Add-ins at Run-time</title><link>http://monoaddins.codeplex.com/wikipage?title=Handling Add-ins at Run-time&amp;version=7</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Handling Add-ins at Run-time&lt;/h1&gt;
&lt;br /&gt;The Mono.Addins API provides several classes to be used by add-in hosts for handling add-ins at run-time. Most of the operations can be done with the class Mono.Addins.AddinManager, which provides methods for:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;initializing the add-in engine,&lt;/li&gt;
&lt;li&gt;getting nodes from extension points,&lt;/li&gt;
&lt;li&gt;subscribing to extension events.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Initialization of the add-in manager"&gt;&lt;/a&gt;
&lt;h2&gt;Initialization of the add-in manager&lt;/h2&gt;
The first thing an add-in host has to do before using any of the Mono.Addins classes is to initialize the add-in engine using the AddinManager.Initialize() method. It&amp;#39;s a very simple operation:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; TextEditorApplication
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Main ()
	{
		&lt;span style="color:Green;"&gt;// Initialize the add-in engine&lt;/span&gt;
		AddinManager.Initialize (&lt;span style="color:#A31515;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;);
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This method has several optional parameters which specify the location of the application add-ins and other settings:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt; Parameter &lt;/th&gt;&lt;th&gt; Description &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; configDir &lt;/td&gt;&lt;td&gt; Directory where the add-in engine configuration information will be stored. If the path is relative, it is assumed to be relative to the application path. If no value is provided, the global location /etc/mono.addins will be used. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; addinsDir &lt;/td&gt;&lt;td&gt; Directory where to look for add-ins. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the relative directory &amp;quot;addins&amp;quot; is used (that is, the directory will be &lt;i&gt;configDir&lt;/i&gt;/addins &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; databaseDir &lt;/td&gt;&lt;td&gt; Directory where to create the add-in cache database. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the &lt;i&gt;configDir&lt;/i&gt; path is used. &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://monoaddins.codeplex.com/wikipage?title=Add-in%20discovery&amp;referringTitle=Handling%20Add-ins%20at%20Run-time"&gt;Add-in discovery&lt;/a&gt; for more information about how add-ins are found and loaded.&lt;br /&gt;&lt;a name="Querying Extension Points"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Extension Points&lt;/h2&gt;
The &lt;b&gt;AddinManager&lt;/b&gt; class offers several methods for getting extensions from an extension point. The most basic method is &lt;b&gt;GetExtensionNodes&lt;/b&gt;, which can be used like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	Console.WriteLine (&lt;span style="color:#A31515;"&gt;&amp;quot;Command: &amp;quot;&lt;/span&gt; + node.Id);
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;It is important to notice that getting the extensions of a node won&amp;#39;t normally result in loading any add-in. The add-in engine is able to extract the needed information from add-ins without having to load them.&lt;br /&gt;&lt;br /&gt;The nodes returned from GetExtensionNodes will have the actual node type, depending on the node name that was used by add-ins to register them. So, for the StartupCommands commands extension (described in the previous chapter) it would be safe to do:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (TypeExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	ICommand command = (ICommand) node.CreateInstance ();
	command.Run ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension points based on TypeExtensionNode"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Type-bound Extension Points&lt;/h2&gt;
The AddinManager class provides the method &lt;b&gt;GetExtensionObjects&lt;/b&gt; (with several overloads) for querying extension points which are bound to types (that is, whose extension nodes are of type TypeExtensionNode). This method works like GetExtensionNode, but instead of returning a node, it casts the node to TypeExtensionNode and returns the result of calling CreateInstance (or optionally GetInstance).&lt;br /&gt;&lt;br /&gt;For example, the previous GetExtensionNodes call might be simplified like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;If the extension point was declared using the TypeExtensionPointAttribute, you can specify a type reference instead of an extension path:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(ICommand)))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Object Lifetime"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Object Lifetime&lt;/h2&gt;
When querying and extension point, Mono.Addins provides three different ways of managing the creation of extension objects:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Shared objects&lt;/b&gt;: objects are created only once and shared in all queries. This is the default mode.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Non-shared objects&lt;/b&gt;: a new object is created for every query.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Shared by context&lt;/b&gt;: like Shared Objects, but only within a specific context.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;By default, &lt;b&gt;GetExtensionObjects&lt;/b&gt; returns &lt;b&gt;shared objects&lt;/b&gt;.. The first time an extension point is queried, the add-in engine creates an instance of the extension objects to be returned. Those instances are cached, so the next time the extension point is queried, the same set of objects is returned. The &lt;b&gt;GetExtensionObjects&lt;/b&gt; method has an optional &lt;b&gt;reuseInstances&lt;/b&gt; parameter which can be set to False to get a set of &lt;b&gt;non-shared objects&lt;/b&gt; from the extension point. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// This first loop will create instances of each type registered in the extension point&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// The second loop will reuse and return the same instances created in the previous loop&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// This loop will create new instances, since the &amp;#39;reuseInstances&amp;#39; parameter is set to false&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;false&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Objects can also be &lt;b&gt;shared by context&lt;/b&gt;. Mono.Addins allows creating different Extension Contexts out of the extension model. Each extension context manages the object lifetime independently. Objects which are shared in one context will not be shared with other contexts. A context can be created using  the &lt;b&gt;AddinManager.CreateExtensionContext ()&lt;/b&gt; method. This method returns an ExtensionContext instance, which has methods for querying extension points, just like &lt;b&gt;AddinManager&lt;/b&gt;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// Create two different contexts&lt;/span&gt;
ExtensionContext ctx1 = AddinManager.CreateExtensionContext ();
ExtensionContext ctx2 = AddinManager.CreateExtensionContext ();

(...)

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx1.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances,&lt;/span&gt;
&lt;span style="color:Green;"&gt;// but the instances are not the same as the ones returned for ctx1&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx2.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Events"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Events&lt;/h2&gt;
AddinManager offers several event sources to which add-in hosts can subscribe to be notified when an extension node is added or removed from an extension point. This may happen in two cases:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;When an add-in is installed/uninstalled or enabled/disabled from inside a host application.&lt;/li&gt;
&lt;li&gt;When there are extension nodes bound to conditions, and the status of those conditions change.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Using extension change events, it is possible to implement applications which can support dynamic activation and deactivation of add-ins at run-time.&lt;br /&gt;&lt;br /&gt;There are two kind of extension change events:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.ExtensionChanged&lt;/b&gt; event. 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.&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.AddExtensionNodeHandler (path, hanlder)&lt;/b&gt;: 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.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;It is important to notice that when a host calls AddExtensionNodeHandler to register a handler, &lt;b&gt;the handler will be called once for all nodes currently existing in the provided path&lt;/b&gt;. This behavior allows writing code like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; CommandManager
{
	&lt;span style="color:Green;"&gt;// A list of commands&lt;/span&gt;
	ArrayList commands = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; ArrayList ();

	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; CommandManager ()
	{
		&lt;span style="color:Green;"&gt;// Registers to node changes in the Commands path&lt;/span&gt;
		AddinManager.AddExtensionNodeHandler (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/Commands&amp;quot;&lt;/span&gt;, OnExtensionChanged);
	}

	&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnExtensionChanged (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, ExtensionNodeEventArgs args)
	{
		&lt;span style="color:Green;"&gt;// Called when a node is added or removed&lt;/span&gt;
		ICommand command = (ICommand) args.ExtensionObject;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (args.Change == ExtensionChange.Add)
			commands.Add (command.Run ());
		&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
			commands.Remove (command.Run ());
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;In this example a CommandManager object subscribes to the extension change event for the path &amp;quot;/TextEditor/Commands&amp;quot;. The idea is to keep all registered commands in a &amp;#39;&amp;#39;commands&amp;#39;&amp;#39; list. The class doesn&amp;#39;t need to do any initialization of the commands list, because the call to AddExtensionNodeHandler will already fire an event of type &amp;#39;&amp;#39;Add&amp;#39;&amp;#39; for every existing node.&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 18:44:45 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Handling Add-ins at Run-time 20110221064445P</guid></item><item><title>Updated Wiki: Handling Add-ins at Run-time</title><link>http://monoaddins.codeplex.com/wikipage?title=Handling Add-ins at Run-time&amp;version=6</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Handling Add-ins at Run-time&lt;/h1&gt;
&lt;br /&gt;The Mono.Addins API provides several classes to be used by add-in hosts for handling add-ins at run-time. Most of the operations can be done with the class Mono.Addins.AddinManager, which provides methods for:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;initializing the add-in engine,&lt;/li&gt;
&lt;li&gt;getting nodes from extension points,&lt;/li&gt;
&lt;li&gt;subscribing to extension events.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Initialization of the add-in manager"&gt;&lt;/a&gt;
&lt;h2&gt;Initialization of the add-in manager&lt;/h2&gt;
The first thing an add-in host has to do before using any of the Mono.Addins classes is to initialize the add-in engine using the AddinManager.Initialize() method. It&amp;#39;s a very simple operation:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; TextEditorApplication
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Main ()
	{
		&lt;span style="color:Green;"&gt;// Initialize the add-in engine&lt;/span&gt;
		AddinManager.Initialize (&lt;span style="color:#A31515;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;);
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This method has several optional parameters which specify the location of the application add-ins and other settings:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt; Parameter &lt;/th&gt;&lt;th&gt; Description &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; configDir &lt;/td&gt;&lt;td&gt; Directory where the add-in engine configuration information will be stored. If the path is relative, it is assumed to be relative to the application path. If no value is provided, the global location /etc/mono.addins will be used. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; addinsDir &lt;/td&gt;&lt;td&gt; Directory where to look for add-ins. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the relative directory &amp;quot;addins&amp;quot; is used (that is, the directory will be &lt;i&gt;configDir&lt;/i&gt;/addins &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; databaseDir &lt;/td&gt;&lt;td&gt; Directory where to create the add-in cache database. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the &lt;i&gt;configDir&lt;/i&gt; path is used. &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="Querying Extension Points"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Extension Points&lt;/h2&gt;
The &lt;b&gt;AddinManager&lt;/b&gt; class offers several methods for getting extensions from an extension point. The most basic method is &lt;b&gt;GetExtensionNodes&lt;/b&gt;, which can be used like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	Console.WriteLine (&lt;span style="color:#A31515;"&gt;&amp;quot;Command: &amp;quot;&lt;/span&gt; + node.Id);
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;It is important to notice that getting the extensions of a node won&amp;#39;t normally result in loading any add-in. The add-in engine is able to extract the needed information from add-ins without having to load them.&lt;br /&gt;&lt;br /&gt;The nodes returned from GetExtensionNodes will have the actual node type, depending on the node name that was used by add-ins to register them. So, for the StartupCommands commands extension (described in the previous chapter) it would be safe to do:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (TypeExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	ICommand command = (ICommand) node.CreateInstance ();
	command.Run ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension points based on TypeExtensionNode"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Type-bound Extension Points&lt;/h2&gt;
The AddinManager class provides the method &lt;b&gt;GetExtensionObjects&lt;/b&gt; (with several overloads) for querying extension points which are bound to types (that is, whose extension nodes are of type TypeExtensionNode). This method works like GetExtensionNode, but instead of returning a node, it casts the node to TypeExtensionNode and returns the result of calling CreateInstance (or optionally GetInstance).&lt;br /&gt;&lt;br /&gt;For example, the previous GetExtensionNodes call might be simplified like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;If the extension point was declared using the TypeExtensionPointAttribute, you can specify a type reference instead of an extension path:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(ICommand)))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Object Lifetime"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Object Lifetime&lt;/h2&gt;
When querying and extension point, Mono.Addins provides three different ways of managing the creation of extension objects:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Shared objects&lt;/b&gt;: objects are created only once and shared in all queries. This is the default mode.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Non-shared objects&lt;/b&gt;: a new object is created for every query.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Shared by context&lt;/b&gt;: like Shared Objects, but only within a specific context.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;By default, &lt;b&gt;GetExtensionObjects&lt;/b&gt; returns &lt;b&gt;shared objects&lt;/b&gt;.. The first time an extension point is queried, the add-in engine creates an instance of the extension objects to be returned. Those instances are cached, so the next time the extension point is queried, the same set of objects is returned. The &lt;b&gt;GetExtensionObjects&lt;/b&gt; method has an optional &lt;b&gt;reuseInstances&lt;/b&gt; parameter which can be set to False to get a set of &lt;b&gt;non-shared objects&lt;/b&gt; from the extension point. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// This first loop will create instances of each type registered in the extension point&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// The second loop will reuse and return the same instances created in the previous loop&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// This loop will create new instances, since the &amp;#39;reuseInstances&amp;#39; parameter is set to false&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;false&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Objects can also be &lt;b&gt;shared by context&lt;/b&gt;. Mono.Addins allows creating different Extension Contexts out of the extension model. Each extension context manages the object lifetime independently. Objects which are shared in one context will not be shared with other contexts. A context can be created using  the &lt;b&gt;AddinManager.CreateExtensionContext ()&lt;/b&gt; method. This method returns an ExtensionContext instance, which has methods for querying extension points, just like &lt;b&gt;AddinManager&lt;/b&gt;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// Create two different contexts&lt;/span&gt;
ExtensionContext ctx1 = AddinManager.CreateExtensionContext ();
ExtensionContext ctx2 = AddinManager.CreateExtensionContext ();

(...)

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx1.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances,&lt;/span&gt;
&lt;span style="color:Green;"&gt;// but the instances are not the same as the ones returned for ctx1&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx2.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Events"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Events&lt;/h2&gt;
AddinManager offers several event sources to which add-in hosts can subscribe to be notified when an extension node is added or removed from an extension point. This may happen in two cases:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;When an add-in is installed/uninstalled or enabled/disabled from inside a host application.&lt;/li&gt;
&lt;li&gt;When there are extension nodes bound to conditions, and the status of those conditions change.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Using extension change events, it is possible to implement applications which can support dynamic activation and deactivation of add-ins at run-time.&lt;br /&gt;&lt;br /&gt;There are two kind of extension change events:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.ExtensionChanged&lt;/b&gt; event. 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.&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.AddExtensionNodeHandler (path, hanlder)&lt;/b&gt;: 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.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;It is important to notice that when a host calls AddExtensionNodeHandler to register a handler, &lt;b&gt;the handler will be called once for all nodes currently existing in the provided path&lt;/b&gt;. This behavior allows writing code like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; CommandManager
{
	&lt;span style="color:Green;"&gt;// A list of commands&lt;/span&gt;
	ArrayList commands = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; ArrayList ();

	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; CommandManager ()
	{
		&lt;span style="color:Green;"&gt;// Registers to node changes in the Commands path&lt;/span&gt;
		AddinManager.AddExtensionNodeHandler (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/Commands&amp;quot;&lt;/span&gt;, OnExtensionChanged);
	}

	&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnExtensionChanged (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, ExtensionNodeEventArgs args)
	{
		&lt;span style="color:Green;"&gt;// Called when a node is added or removed&lt;/span&gt;
		ICommand command = (ICommand) args.ExtensionObject;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (args.Change == ExtensionChange.Add)
			commands.Add (command.Run ());
		&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
			commands.Remove (command.Run ());
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;In this example a CommandManager object subscribes to the extension change event for the path &amp;quot;/TextEditor/Commands&amp;quot;. The idea is to keep all registered commands in a &amp;#39;&amp;#39;commands&amp;#39;&amp;#39; list. The class doesn&amp;#39;t need to do any initialization of the commands list, because the call to AddExtensionNodeHandler will already fire an event of type &amp;#39;&amp;#39;Add&amp;#39;&amp;#39; for every existing node.&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 18:42:33 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Handling Add-ins at Run-time 20110221064233P</guid></item><item><title>Updated Wiki: Handling Add-ins at Run-time</title><link>http://monoaddins.codeplex.com/wikipage?title=Handling Add-ins at Run-time&amp;version=5</link><description>&lt;div class="wikidoc"&gt;&lt;h1&gt;Handling Add-ins at Run-time&lt;/h1&gt;
&lt;br /&gt;The Mono.Addins API provides several classes to be used by add-in hosts for handling add-ins at run-time. Most of the operations can be done with the class Mono.Addins.AddinManager, which provides methods for:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;initializing the add-in engine,&lt;/li&gt;
&lt;li&gt;getting nodes from extension points,&lt;/li&gt;
&lt;li&gt;subscribing to extension events.&lt;/li&gt;&lt;/ul&gt;
&lt;a name="Initialization of the add-in manager"&gt;&lt;/a&gt;
&lt;h2&gt;Initialization of the add-in manager&lt;/h2&gt;
The first thing an add-in host has to do before using any of the Mono.Addins classes is to initialize the add-in engine using the AddinManager.Initialize() method. It&amp;#39;s a very simple operation:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;class&lt;/span&gt; TextEditorApplication
{
	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; &lt;span style="color:Blue;"&gt;static&lt;/span&gt; &lt;span style="color:Blue;"&gt;void&lt;/span&gt; Main ()
	{
		&lt;span style="color:Green;"&gt;// Initialize the add-in engine&lt;/span&gt;
		AddinManager.Initialize (&lt;span style="color:#A31515;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;);
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This method has several optional parameters which specify the location of the application add-ins and other settings:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt; Parameter &lt;/th&gt;&lt;th&gt; Description &lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; configDir &lt;/td&gt;&lt;td&gt; Directory where the add-in engine configuration information will be stored. If no value is provided, the global location /etc/mono.addins will be used. &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; addinsDir &lt;/td&gt;&lt;td&gt; Directory where to look for add-ins. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the relative directory &amp;quot;addins&amp;quot; is used (that is, the directory will be &lt;i&gt;configDir&lt;/i&gt;/addins &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt; databaseDir &lt;/td&gt;&lt;td&gt; Directory where to create the add-in cache database. If the path is relative, it is assumed to be relative to &lt;i&gt;configDir&lt;/i&gt;. If not specified, the &lt;i&gt;configDir&lt;/i&gt; path is used. &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="Querying Extension Points"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Extension Points&lt;/h2&gt;
The &lt;b&gt;AddinManager&lt;/b&gt; class offers several methods for getting extensions from an extension point. The most basic method is &lt;b&gt;GetExtensionNodes&lt;/b&gt;, which can be used like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	Console.WriteLine (&lt;span style="color:#A31515;"&gt;&amp;quot;Command: &amp;quot;&lt;/span&gt; + node.Id);
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;It is important to notice that getting the extensions of a node won&amp;#39;t normally result in loading any add-in. The add-in engine is able to extract the needed information from add-ins without having to load them.&lt;br /&gt;&lt;br /&gt;The nodes returned from GetExtensionNodes will have the actual node type, depending on the node name that was used by add-ins to register them. So, for the StartupCommands commands extension (described in the previous chapter) it would be safe to do:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (TypeExtensionNode node &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionNodes (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;)) {
	ICommand command = (ICommand) node.CreateInstance ();
	command.Run ();
}
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension points based on TypeExtensionNode"&gt;&lt;/a&gt;
&lt;h2&gt;Querying Type-bound Extension Points&lt;/h2&gt;
The AddinManager class provides the method &lt;b&gt;GetExtensionObjects&lt;/b&gt; (with several overloads) for querying extension points which are bound to types (that is, whose extension nodes are of type TypeExtensionNode). This method works like GetExtensionNode, but instead of returning a node, it casts the node to TypeExtensionNode and returns the result of calling CreateInstance (or optionally GetInstance).&lt;br /&gt;&lt;br /&gt;For example, the previous GetExtensionNodes call might be simplified like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/StartupCommands&amp;quot;&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;If the extension point was declared using the TypeExtensionPointAttribute, you can specify a type reference instead of an extension path:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects (&lt;span style="color:Blue;"&gt;typeof&lt;/span&gt;(ICommand)))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Object Lifetime"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Object Lifetime&lt;/h2&gt;
When querying and extension point, Mono.Addins provides three different ways of managing the creation of extension objects:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Shared objects&lt;/b&gt;: objects are created only once and shared in all queries. This is the default mode.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Non-shared objects&lt;/b&gt;: a new object is created for every query.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Shared by context&lt;/b&gt;: like Shared Objects, but only within a specific context.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;By default, &lt;b&gt;GetExtensionObjects&lt;/b&gt; returns &lt;b&gt;shared objects&lt;/b&gt;.. The first time an extension point is queried, the add-in engine creates an instance of the extension objects to be returned. Those instances are cached, so the next time the extension point is queried, the same set of objects is returned. The &lt;b&gt;GetExtensionObjects&lt;/b&gt; method has an optional &lt;b&gt;reuseInstances&lt;/b&gt; parameter which can be set to False to get a set of &lt;b&gt;non-shared objects&lt;/b&gt; from the extension point. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// This first loop will create instances of each type registered in the extension point&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// The second loop will reuse and return the same instances created in the previous loop&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// This loop will create new instances, since the &amp;#39;reuseInstances&amp;#39; parameter is set to false&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; AddinManager.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;false&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Objects can also be &lt;b&gt;shared by context&lt;/b&gt;. Mono.Addins allows creating different Extension Contexts out of the extension model. Each extension context manages the object lifetime independently. Objects which are shared in one context will not be shared with other contexts. A context can be created using  the &lt;b&gt;AddinManager.CreateExtensionContext ()&lt;/b&gt; method. This method returns an ExtensionContext instance, which has methods for querying extension points, just like &lt;b&gt;AddinManager&lt;/b&gt;. For example:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Green;"&gt;// Create two different contexts&lt;/span&gt;
ExtensionContext ctx1 = AddinManager.CreateExtensionContext ();
ExtensionContext ctx2 = AddinManager.CreateExtensionContext ();

(...)

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx1.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();

&lt;span style="color:Green;"&gt;// Every time this loop is executed, it will process the same set of instances,&lt;/span&gt;
&lt;span style="color:Green;"&gt;// but the instances are not the same as the ones returned for ctx1&lt;/span&gt;
&lt;span style="color:Blue;"&gt;foreach&lt;/span&gt; (ICommand cmd &lt;span style="color:Blue;"&gt;in&lt;/span&gt; ctx2.GetExtensionObjects&amp;lt;ICommand&amp;gt; (&lt;span style="color:Blue;"&gt;true&lt;/span&gt;))
	cmd.Run ();
&lt;/pre&gt;&lt;/div&gt;&lt;a name="Extension Events"&gt;&lt;/a&gt;
&lt;h2&gt;Extension Events&lt;/h2&gt;
AddinManager offers several event sources to which add-in hosts can subscribe to be notified when an extension node is added or removed from an extension point. This may happen in two cases:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;When an add-in is installed/uninstalled or enabled/disabled from inside a host application.&lt;/li&gt;
&lt;li&gt;When there are extension nodes bound to conditions, and the status of those conditions change.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;Using extension change events, it is possible to implement applications which can support dynamic activation and deactivation of add-ins at run-time.&lt;br /&gt;&lt;br /&gt;There are two kind of extension change events:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.ExtensionChanged&lt;/b&gt; event. 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.&lt;/li&gt;&lt;/ul&gt;

&lt;ul&gt;&lt;li&gt;&lt;b&gt;AddinManager.AddExtensionNodeHandler (path, hanlder)&lt;/b&gt;: 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.&lt;/li&gt;&lt;/ul&gt;
&lt;br /&gt;It is important to notice that when a host calls AddExtensionNodeHandler to register a handler, &lt;b&gt;the handler will be called once for all nodes currently existing in the provided path&lt;/b&gt;. This behavior allows writing code like this:&lt;br /&gt;&lt;br /&gt;&lt;div style="color:Black;background-color:White;"&gt;&lt;pre&gt;
&lt;span style="color:Blue;"&gt;class&lt;/span&gt; CommandManager
{
	&lt;span style="color:Green;"&gt;// A list of commands&lt;/span&gt;
	ArrayList commands = &lt;span style="color:Blue;"&gt;new&lt;/span&gt; ArrayList ();

	&lt;span style="color:Blue;"&gt;public&lt;/span&gt; CommandManager ()
	{
		&lt;span style="color:Green;"&gt;// Registers to node changes in the Commands path&lt;/span&gt;
		AddinManager.AddExtensionNodeHandler (&lt;span style="color:#A31515;"&gt;&amp;quot;/TextEditor/Commands&amp;quot;&lt;/span&gt;, OnExtensionChanged);
	}

	&lt;span style="color:Blue;"&gt;void&lt;/span&gt; OnExtensionChanged (&lt;span style="color:Blue;"&gt;object&lt;/span&gt; s, ExtensionNodeEventArgs args)
	{
		&lt;span style="color:Green;"&gt;// Called when a node is added or removed&lt;/span&gt;
		ICommand command = (ICommand) args.ExtensionObject;
		&lt;span style="color:Blue;"&gt;if&lt;/span&gt; (args.Change == ExtensionChange.Add)
			commands.Add (command.Run ());
		&lt;span style="color:Blue;"&gt;else&lt;/span&gt;
			commands.Remove (command.Run ());
	}
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;In this example a CommandManager object subscribes to the extension change event for the path &amp;quot;/TextEditor/Commands&amp;quot;. The idea is to keep all registered commands in a &amp;#39;&amp;#39;commands&amp;#39;&amp;#39; list. The class doesn&amp;#39;t need to do any initialization of the commands list, because the call to AddExtensionNodeHandler will already fire an event of type &amp;#39;&amp;#39;Add&amp;#39;&amp;#39; for every existing node.&lt;br /&gt;&lt;/div&gt;&lt;div class="ClearBoth"&gt;&lt;/div&gt;</description><author>slluis</author><pubDate>Mon, 21 Feb 2011 18:36:24 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Handling Add-ins at Run-time 20110221063624P</guid></item></channel></rss>