Frequently Asked Questions

About Mono.Addins

What is Mono.Addins?

Mono.Addins is a generic framework for creating extensible applications, and for creating libraries which extend those applications.

Mono.Addins has been designed to be easy to use and useful for a wide range of applications: from simple applications with small extensibility needs, to complex applications which need support for large add-in structures.

Mono.Addins is just an add-in engine. It intends to be as small as possible, and avoids imposing an architecture on the host application. All the effort has been focused in building an add-in engine which is fast, memory efficient and scalable (a host can efficiently handle thousands of add-ins).

What's the difference between Mono.Addins and System.AddIn included in .NET 3.5?

Mono.Addins has a different set of features, and it is more generic. System.AddIn is based on the concept of dynamically discovering and instantiating types in an (optionally) isolated execution context. Mono.Addins is based on a more generic concept of extension, so you can dynamically discover and load extensions which are not just 'types' but they can be data of any kind (for example, an extension could be an image or a menu item).

What's the license of Mono.Addins?

The license of Mono.Addins is MIT X11.

Is there any guarantee of stability in the API?

The API is currently stable and there are no plans to break compatibility with old versions.

Using Mono.Addins

What is an add-in host?

An add-in host is an application or library which can be extended by add-ins.
There are two main reasons for converting an application into an add-in host:
  • Make it possible for third parties to add new functionality to the application.
  • Make the application more modular, by decoupling the consumer of a service (the host) from the provider of that service (the add-in).

In the most common case, an add-in host is an application which defines an interface to be implemented by add-ins. However, extensibility is not limited to implementing interfaces. An application can be extended in many ways: by adding new menu items, additional documentation, document templates, etc.

An add-in host exposes all possible extensions by using extension points.

What is an add-in root?

The same as an add-in host.

What is an add-in?

A set of files which register new nodes in one or several extension points defined by add-in hosts. An add-in can also act as an add-in host, and as such it can be extended by other add-ins.

What is an extension point?

An application may be extended in different ways. An extension point is a formal description of one of those extension possibilities.

Extension points consist of:
  • A path which identifies the extension point. When an add-in wants to extend an application, it has to specify the path of the extension point it wants to extend.
  • A description of the kind of data that the extension point accepts. By default, extension points accept type names (which allow specifying for example a class that implements a service), although they can also be defined to accept other kind of data such as menu items or whatever an application needs. This data type description is done with one or more extension node definitions.

What is an extension node?

An extension node is the definition of an object that extends an application. For example, it can be the definition of a service, or a menu item.

It is important to differentiate between the definition of the object (the extension node) and the object itself. For example, the definition of a service may be the name of the class that implements the service. The definition of a menu item is a set of attributes which include the name, the icon and the command to execute.

Add-ins use extension nodes to register extensions in a specific extension point. Extension nodes are typed, and extension points define the types of nodes they accept.

Should I use XML manifests or attributes to describe an add-in?

Add-ins can be described either using a set of custom attributes defined by Mono.Addins, and which can be applied to classes and interfaces, or using an XML manifest.

When possible, using custom attributes is more convenient, since they are easier to use, less prone to errors, and make the code easier to understand. However, custom attributes have limitations, so you may need to use XML manifests in some cases, especially when dealing with data-only extension points.

Some notes:
  • Add-in manifests can be embedded as resources.
  • It is allowed to use a mix of both approaches to describe an add-in. That is, an add-in could declare simple extensions using attributes, and more complex extensions in a manifest embedded as a resource.
  • By using manifests it is possible to create add-ins which don't include any assembly. For example, a document template extension for a text editor might include the xml manifest declaring the template, and the template itself (maybe another xml file). No assemblies are involved here.

Where should add-in manifests be placed?

In general, the best option is to embed the manifest as a resource in the assembly that implements the add-in or host.

If for some reason you don't want or can't embed it as a resource, it should be placed in the same directory where you placed the assembly.

Where does Mono.Addins look for add-ins?

By default, Mono.Addins looks for add-ins in the following locations:
  • The directory of the application (not in sub-directories).
  • The 'addins' sub-directory of the add-in registry used by the application. For example, if the application is initialized with AddinManager.Initialize ("/foo/bar"), the add-ins folder would be '/foo/bar/addins'.

Is it possible to specify a list of folders where to look for add-ins?

Yes. In any of the default add-in folders (see previous question) you can place a file with the extension .addins, and with the contents described here. In this file you can specify other folders (relative or absolute) to be included in the search for add-ins.

Does Mono.Addins scan all add-ins every time I start the application?

No, by default it doesn't. Add-ins are scanned the first time the application is started, and all information about the hosts and add-ins is stored in a database (located at the registry directory).

When the application is started again, all required information is gathered from the database.

To ensure that the database is always up-to-date when starting the application, you can add this method just after the add-in manager initialization:

AddinManager.Registry.Update ()

This call will scan the add-in folders and detect new add-ins and changes in existing add-ins, and will update the database. Add-ins are only fully scanned if changes are detected, so it is a fast operation in most of cases.

Does Mono.Addins support localized add-ins?

Yes, you can create localizable add-ins using gettext or string resources.

Is it possible to reference generic types in extension nodes in an XML manifest?

Yes, by using the .NET standard syntax for generic types, for example:

<ExtensionNode name="My" type="MyExtension'1[Type]" />

What are add-in namespaces and what can be used for?

Namespaces can be used to avoid add-in and host name collisions when using different kind of extensible applications and libraries together.

For example, if NUnit was based on Mono.Addins it could use 'NUnit' as namespace for all the root libraries and add-ins. On the other hand, MonoDevelop could use the 'MonoDevelop' namespace. When using NUnit together with MonoDevelop, there would no danger of add-in name collision.

Does Mono.Addins support add-in isolation using application domains?

Right now it is not supported, but it's something we might add if people need it. Notice that using app-domains is not always possible. For example, if the add-in needs to extend a gtk# user interface (which is a very common case), it won't we able to use app-domains since gtk# can only run in the main domain.

Troubleshooting

My application doesn't find any or some of the add-ins, why is that?

There are some quick checks you can do:
  • Make sure the add-in registry is up-to-date. The best way to ensure that is to make a call like AddinManager.Registry.Update () after the add-in manager initialization. This will scan the add-in folders looking for new or updated add-ins.
  • Make sure all dependencies are properly declared in your add-in. If an add-in extends an extension point declared in an add-in host or in another add-in, that host/add-in should be included in the dependencies list.
  • Make sure that extension points are always queried from the assemblies that declare them. Trying to get nodes from an extension point declared in an external add-in or host is not supported.
  • If you are using an add-in manifest (.addin.xml file) make sure the manifest is embedded as resource into the add-in assembly.

If everything seems to be correct, you may try diagnosing the problem by running this command:

mautil -reg <path-to-registry> -p <path-to-application> reg-build -v


Where <path-to-registry> is the path you used to initialize the add-in registry (the parameter in the AddinManager.Initialize call), and <path-to-application> is the path to the directory containing the application assemblies.

This command will regenerate the add-in registry and will print an output similar to this:

MonoDevelop Add-in Setup Utility
Checking: /usr/lib/monodevelop/bin
Checking: /usr/lib/monodevelop/AddIns
Checking: /usr/lib/monodevelop/AddIns/AspNetEdit
Checking: /usr/lib/monodevelop/AddIns/BackendBindings
(...)
Checking: /usr/lib/monodevelop/AddIns/NUnit
Checking: /usr/lib/monodevelop/AddIns/VersionControl
Checking: /usr/lib/monodevelop/AddIns/WelcomePage
Folders checked (97 ms)
Looking for addins
Using assembly reflector: Mono.Addins.CecilReflector.Reflector
Scanning file: /usr/lib/monodevelop/bin/Mono.Cecil.Mdb.dll
Scanning file: /usr/lib/monodevelop/bin/Mono.Cecil.dll
Scanning file: /usr/lib/monodevelop/bin/Mono.Debugging.dll
Scanning file: /usr/lib/monodevelop/bin/Mono.TextEditor.dll
(...)
Scanning file: /usr/lib/monodevelop/bin/MonoDevelop.Components.dll
Scanning file: /usr/lib/monodevelop/bin/MonoDevelop.Core.Gui.dll
Scanning file: /usr/lib/monodevelop/AddIns/MonoDeveloperExtensions/MonoDeveloperExtensions.dll
Scanning file: /usr/lib/monodevelop/AddIns/NUnit/MonoDevelop.NUnit.dll
Folders scan completed (3206 ms)
Regenerating all add-in relations.
Generating add-in extension maps
Addin relation map generated.
  Addins Updated: 57
  Extension points: 152
  Extensions: 423
  Extension nodes: 1920
  Node sets: 11
Add-in relations analyzed (281 ms)


Review the output and make sure that the folder where your add-in is placed is included in a "Checking:" line. If it isn't, maybe you need to include the folder by using a .addins file.

Also check that the add-in is included in a "Scanning file" line. If it isn't it means that the add-in is not being detected. It may happen if you forgot to include the add-in manifest, or the [Addin] attribute if you are not using a manifest.

The tool can also report errors or warnings. A common case of failure is an add-in depending on a library which can't be loaded for some reason.

Last edited Nov 7, 2010 at 9:20 AM by slluis, version 3

Comments

No comments yet.