Mono.Addins provides a very flexible model for specifying where add-ins should be looked up.
An application can define which directories should be scanned when looking for add-ins. However, add-ins copied to those directories won't be detected until an explicit add-in scan is requested to the add-in engine. That's because Mono.Addins keeps
all add-in information in a Registry
which needs to be updated if there is any change. The registry can be updated by an application by calling
, or by a user by running the add-in setup tool.
The registry has information about the location of every add-in and a timestamp of the last check, so the Update method will only scan new or modified add-ins. An application might add a call to AddinManager.Registry.Update() in the Main method to detect all
new add-ins every time the app is started.
Every add-in added to the registry is parsed and validated, and if there is any error it will be rejected. The registry is also in charge of scanning the add-in assemblies and look for extensions and other information declared using custom attributes. That
information is merged with the manifest information (if there is one) to create a complete add-in description ready to be used at run-time.
It's important to notice that Mono.Addins allows sharing an add-in registry among several applications
. In this context, all applications sharing the registry share the same extension point tree, and it is possible to implement add-ins which extend
Initialization of the Add-in Registry
Mono.Addins allows sharing an add-in registry among several applications, so one important decision that an application developer has to make is which add-in registry the application is going to use. There are several options:
- Use an application specific add-in registry. This registry will be private to the application.
- Share a registry with other applications. The application needs to know where this registry is located and properly initialize the add-in engine.
- Use the global add-in registry. If no particular registry is specified, the application will use a global registry shared among all applications configured in the same way.
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. This method can take a path to the registry as parameter. If none is provided, the global registry
will be used.
Location of registries
Add-in registries should always be created in the home directory of the user. Otherwise, a registry might end referencing add-ins located in home directories of several users, which would easily lead to conflicts.
The best location for application specific add-in registries is the configuration directory of the application. For example: "~/.config/MyApp".
In any case, the user must have read and write permissions for the directory where the registry is located.
First of all, let's define the concept of add-in folder
. An add-in folder is a file system directory which can contain:
- Add-in implementations, published either as standalone assemblies (with or without an embedded manifest), or as a manifest files referencing assemblies.
- Files with the extension ''.addins'' which contain links to other add-in folders.
file looks like this:
When a registry is looking for add-ins in a folder and it finds a ''.addins'' file, it will parse it and will start recursively looking for add-ins in the referenced folders (which can also contain other .addins files).
element can be used to specify new add-in folders. The search is not recursive by default, but it can be made recursive using the
element can be used to exclude a patch from the add-in search. The provided path can be a directory or a specific file.
The default add-in folder
For every add-in registry there is an add-in folder where the registry will look for add-ins by default. This folder is an "addins" subdirectory of the directory where the repository is located. In most cases, this folder will only contain .addins
files referencing other more convenient locations for add-ins.
Add-in folders for host applications
When a host application is started for the first time, a .addins file referencing the location of the application will automatically be created in the default add-in folder. This is needed because not only add-ins need to be discoverable, but also add-in roots
need to. This reference ensures that add-in roots are accessible to all add-ins that want to extend them.
User-specific add-in folders
User specific add-in folders allows users to install their own add-ins without interfering with other users. Since registries are located in the user home directory, the "addins" folder of the registry is already a user specific directory, so add-ins
can be installed there.
However, when using a shared add-in registry, an application may want to provide an application (and user) specific add-in folder. The easiest way to do it is to distribute a .addins file in the same application directory referencing a directory starting with
This .addin file will be found thanks to the directory reference that the add-in engine automatically creates for host applications.
System-wide add-in folders
An application may want to have a system wide folder where add-ins for that application can be registered. That's the only way to support add-ins which are to be available to all users of a system.
To support it, the application just has to include a .addins file in the application folder referencing a path which is not user specific.
Add-in folders used by the global add-in registry
The global add-in registry is created in "~/.config/mono.addins", so user specific add-ins can be installed in "~/.config/mono.addins/addins".
System wide add-ins can be referenced by installing .addins files in "/etc/mono.addins" (it is not recomended to install add-ins directly in "/etc/mono.addins").
In any case, an application may also have private user specific or system wide add-in folders, like in the previous cases.
Add-ins in the GAC
Add-ins and add-in roots can be installed in the GAC, but to make them discoverable by the add-in engine, they must be reference from a .addins file, like in the following example:
<GacAssembly>SomeAssembly, Version=0.1.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756</GacAssembly>