Data Files and Resources

Extension Data in Resources

In the previous section we've seen how to use an extension point for registering extension data. Using attribute/value pairs is useful for simple metadata, but it may not be enough for more complex data. For example, let's say we are implementing a text editor and we want to allow add-ins to provide their own document templates. Each template will have a name, an icon and a text document with the template text. This extension point could be declared like this:

using System;
using Mono.Addins;

[assembly:ExtensionPoint ("/DocumentTemplates", ExtensionAttributeType=typeof(DocumentTemplateAttribute))]

public class DocumentTemplateAttribute: Attribute
{
	public DocumentTemplateAttribute ()
	{
	}

	[NodeAttribute]
	public string Name { get; set; }

	[NodeAttribute]
	public string IconResource { get; set; }

	[NodeAttribute]
	public string TemplateResource { get; set; }
}

Notice that using the 'Resource' suffix in the property names is just a convention.

An add-in extending the above extension point would look like this:

using System;
using Mono.Addins;

[assembly:Addin]
[assembly:AddinDependency ("HelloWorld", "1.0")]

[assembly:DocumentTemplate (Name="Letter", IconResource="LetterIcon.png", TemplateResource="Letter.txt")}
[assembly:DocumentTemplate (Name="Fax", IconResource="FaxIcon.png", TemplateResource="Fax.txt")}

The add-in would embed the following files as resources in the add-in assembly: LetterIcon.png, FaxIcon.png, Letter.txt and Fax.txt.

Those extensions could be retrieved by the host application like this:

using System;
using Mono.Addins;

[assembly:AddinRoot ("HelloWorld", "1.0")]

class MainClass
{
	public static void Main ()
	{
		AddinManager.Initialize ();
		AddinManager.Registry.Update ();
		
		foreach (ExtensionNode<DocumentTemplateAttribute> node in AddinManager.GetExtensionNodes ("/DocumentTemplates")) {
			Console.WriteLine ("Loading template: {0}", node.Data.Name);

			// Load the icon
			Stream iconStream = node.Addin.GetResource (node.Data.IconResource);
			Bitmap icon = new Bitmap (iconStream);
			iconStream.Close ();

			// Load the template
			Stream templateStream = node.Addin.GetResource (node.Data.TemplateResource);
			StreamReader sr = new StreamReader (templateStream);
			string templateText = sr.ReadtoEnd ();
			sr.Close ();

			// ... do something with 'icon' and 'templateText'
		}
	}
}

The Addin property of the ExtensionNode class returns an object of type Mono.Addins.RuntimeAddin which can be used to get resources and other kinds of data from the add-in assembly.

The GetResource() method is used in the example to get the stream of a resource.

Extension Data in Add-in Files

Instead of embedding data files as resources, it is also possible to deploy them as standalone files. The same example, using standalone files, would look like this:

using System;
using Mono.Addins;

[assembly:ExtensionPoint ("/DocumentTemplates", ExtensionAttributeType=typeof(DocumentTemplateAttribute))]

public class DocumentTemplateAttribute: Attribute
{
	public DocumentTemplateAttribute ()
	{
	}

	[NodeAttribute]
	public string Name { get; set; }

	[NodeAttribute]
	public string IconFile { get; set; }

	[NodeAttribute]
	public string TemplateFile { get; set; }
}

An add-in extending the above extension point would look like this:

using System;
using Mono.Addins;

[assembly:Addin]
[assembly:AddinDependency ("HelloWorld", "1.0")]

[assembly:DocumentTemplate (Name="Letter", IconFile="LetterIcon.png", TemplateFile="Letter.txt")}
[assembly:DocumentTemplate (Name="Fax", IconFile="FaxIcon.png", TemplateFile="Fax.txt")}

In this case, the included files would not be embedded as resources, but instead provided together with the add-in assembly. The path provided in IconFile and TemplateFile should be relative to the add-in assembly.

Those extensions could be retrieved by the host application like this:

using System;
using Mono.Addins;

[assembly:AddinRoot ("HelloWorld", "1.0")]

class MainClass
{
	public static void Main ()
	{
		AddinManager.Initialize ();
		AddinManager.Registry.Update ();
		
		foreach (ExtensionNode<DocumentTemplateAttribute> node in AddinManager.GetExtensionNodes ("/DocumentTemplates")) {
			Console.WriteLine ("Loading template: {0}", node.Data.Name);

			// Load the icon
			Stream iconStream = File.OpenRead (node.Addin.GetFilePath (node.Data.IconFile));
			Bitmap icon = new Bitmap (iconStream);
			iconStream.Close ();

			// Load the template
			StreamReader sr = new StreamReader (node.Addin.GetFilePath (node.Data.TemplateFile));
			string templateText = sr.ReadtoEnd ();
			sr.Close ();

			// ... do something with 'icon' and 'templateText'
		}
	}
}

Given a relative file name, the GetFilePath() method returns the corresponding absolute path.

Next topic: About Lazy Loading

Last edited May 20, 2010 at 7:01 PM by slluis, version 3

Comments

No comments yet.