Проект "MonoDevelop Add-in для PascalABC.NET"

Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску

Mono.Addins Reference Manual

Введение

Mono.Addins является основой для создания расширяемых приложений, а также для создания библиотек, расширяющих эти приложения(аналог "плагинов").

 Эта структура вытекает из использования MonoDevelop, путем добавления в MonoDevelop расширяемых приложений (extensible applications), хотя MonoDevelop был полностью переписан и усовершенствован, существует множество способов сделать его более общим и простым в использовании. Добавление в программу MonoDevelop "плагинов" (Mono.Addins) реализованно намного удобней, чем по сравнению с инструментом SharpDevelop, который реализован на основе идей от Eclipse add-in engine (добавления "плагинов" в системе Eclipse).

 Mono.Addins был разработан, чтобы быть полезным для широкого спектра приложений: от простых приложений с малыми потребностями расширения(дополнения к коду) до сложных приложений (таких как сам MonoDevelop), которые нуждаются в поддержке: в больших дополнениях в структурах программы.

 Этот документ включает в себя подробное описание всех функций, которые предоставляет Mono.Addins. Если у Вас есть вопросы или предложения о Mono.Addins, подпишитесь на рассылку разработчиков Mono.Addins (http://groups.google.com/group/mono-addins).

Основы Mono.Addins

 Модель расширения Mono.Addins базируется на четырех концепциях:

Add-in host: приложение или библиотека, которые могут быть расширены с помощью add-ins. Расширение возможностей определяется посредством точек расширения(extension points).

Extension point: пространство, гед add-ins могут регистрировать extension nodes(узлы расширекния) для расширения функциональности. Extension points определяются путем использования extension paths(путей расширения).

Extension node: Атрибут оформления элемента, описывающий расширения. Extension nodes(узлы расширения) типизированные. extension points могут объявить, какие типы extension nodes они принимают.

Add-in: Набор файлов, которые регистрируют новые узлы в одной или нескольких точек расширения, определяются add-in hosts. Add-in может дополнять add-in host, и может реализовываться разными add-ins.

 Mono.Addins определяется оделью описания Add-in, с использованием add-ins and add-in hosts для описания индормации расширения. Add-in может быть представлен с использованием XML манифеста(объявления), или с применением атрибутов и типов.

 В результатте Mono.Addins записывается в виде API (выполняя Mono.Addins.dll) который встраивается при выполнении.

 Для примера рассотрим базовое приложение Mono.Addins.

Простейший пример

Реализуем текстовый редактор к которому будем подключать наши add-ins. Рассмотрим диаграмму, на колторой отображена схема работы программы.

Файл:Example.jpg

Далее рассмотрим, как расширить возможности текстового редактора, используя возможности Mono.Addins.

Мы хотим разрешить add-ins выполнять последние изменения при запуске приложения.

Приложение текстового редактора состоит из 2-х сборок:

1)TextEditor.exe это само приложение.

2)TextEditorLib.dll определяет насколько дополнительных интерфейсов для приложения


Далее мы видим базовую структуру.

ICommand library (TextEditorLib.dll)

public interface ICommand

{

string Run ();

}

Это очень просто пример с одним методом: run. Редактор выполяет этот метод в вконце.

Add-in host manifest (TextEditor.addin)

<Addin id="TextEditor" version="1.0" isroot="true">


<Runtime>

<Import assembly="TextEditor.exe"/>

<Import assembly="TextEditorLib.dll"/>

</Runtime>


<ExtensionPoint path = "/TextEditor/StartupCommands">

<ExtensionNode name="Command" type="Mono.Addins.TypeExtensionNode"/>

</ExtensionPoint>

</Addin>

Основной манифест включает следующую информацию:

1)Элемент Addin объявляет главный идентификатор и версию. Корневой атрибут определяет что необходимо добавить в манифест.

2)Элемент времени выполнения определяет файлы принадлежащие хосту.

3)Элемент точки расширения определяет новую точку расширения. Атрибут определяет местоположение точки расширения в дереве расширения.

4)Элемент узла расширения определяет тип узла, который принимает точку расширения. В этом случае, точка расширения позволяет только узлам типа TypeExtensionNode, которые будут определены в расширениях, используя имя Command.

The host application (TextEditor.exe)

public class TextEditorApplication

{

public static void Main ()

{

// Initialize the add-in engine

AddinManager.Initialize ();


// Get the extension nodes in the extension point

foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes ("/TextEditor/StartupCommands")) }

ICommand command = (ICommand) node.CreateInstance ();

command.Run ();

}

} }

Приложение хоста использует Mono.Addins API, чтобы получить узлы зарегистрированных в точке расширения. Для этого:

1)Инициализировать add-in engine, называемый AddinManager.Initialize()

2)Вызываем метод AddinManager.GetExtensionNodes(), чтобы вернуть все зарегистрированные узлы add-ins в точке расширения StartupCommands. Вызов возвращает узлы типа TypeExtensionNode, с точки расширения определенной для такого рода узлов.

3)TypeExtensionNode это особый тип узла, который позволяет указать тип. Он предоставляет методы для создания экземпляров из описанных типов. Принимающий вызов метода CreateInstance на каждом узле, чтобы получить реализацию ICommand, а затем вызывает Запустить на каждом из них.

An add-in (SampleAddin.dll)

class HelloWorldExtension: ICommand {

public string Run ()

{

Console.WriteLine ("Hello World");

}

}

Этот add-in представляет собой простую реализацию интерфейса ICommand.

Add-in manifest (SampleAddin.addin) <Addin>

<Runtime>

<Import assembly="SampleAddin.dll"/>

</Runtime>


<Dependencies>

<Addin id="TextEditor" version="1.0" />

</Dependencies>


<Extension path = "/TextEditor/StartupCommands">

<Command type="HelloWorldExtension" />

</Extension>


</Addin> Add-in манифест схож с главным манифестом(хоста):

1)Здесь Addin корневой элемент, не предоставляет информацию об идентификационном номере или версии. Ид и версии не требуются add-ins, если они объявят новые точки расширения они смогут усовершенствовать add-ins.

2)Зависимый элемент определяет зависимость от других add-ins или add-in hosts.

3)Зависимые элементы могуь использовать описание новых расширений. Свойство определяет точку расширения и расширяется выполнением.

4)Управляющий элемент расширяет узел. Т.к. узлы этой точки расширения имеют тип TypeExtensionNode, мы должна описывать типы атрибутов для описания имени класса. Этот класс будет создан при вызове CreateInstance данного узла.

Элемент является продолжением узла. С узлах этой точки расширения имеют тип TypeExtensionNode, удлинители должны предоставить печатать атрибут, который определяет имя класса, представленного этим узлом. Это класс, который будет создан при вызове CreateInstance узла.

Простой пример использования атрибутов сборки

Данный пример может быть раелизован, использхуя атрибуты сборки вместо xml манифеста. Правда не всеобъявления,которые делаются в манифесте, можно сделать с помощью атрибутов. Но атрибуты активно используются, т.к. они очень удобны, особенно для простых примеров.

ICommand library (TextEditorLib.dll)

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

[TypeExtensionPoint ("/TextEditor/StartupCommands")]

public interface ICommand {

string Run ();

}

Атрибут AddinRoot может быть использован для отметки сборки настройки add-in host. TypeExtensionPoint этот атрибут описывает новую точку расширения с определенным путем для конструктора, и требует узлы типа TypeExtensionNode.

An add-in (SampleAddin.dll)

[assembly:Addin]

[assembly:AddinDependency ("TextEditor", "1.0")]

[Extension ("/TextEditor/StartupCommands")]

class HelloWorldExtension: ICommand

{

public string Run ()

{

Console.WriteLine ("Hello World");

}

}

Addin этот атрибут указывает на сборку add-in. Для этого может использоваться идентификатор или версия при необходимости. AddinDependency- атрибут описывающий зависимости TextEditor от add-in host. Extensio- атрибут указывающий class extension. Для этого регистрируем узел расширения с типом TypeExtensionNode с указанием пути.

Архитектура приложения расширения.

Приложение расширения, состоит как минимум из одной сборки выполнения и одной библиотеки. Mono.Addins основывается на так называемой сильно типизированной модели. Эта модель нуждается в точном объявлени всех точек расширения и иныормации их согласования. Вся эта информация составляет add-in root (корневой add-in).

Add-in roots

Приложения расширения доложны объявлять один, как минимум add-in root, но при необходимости могут объявлять и больше.Определив нсколько add-in roots для приложения состоящего из нескольких модулей. Это один из возможных путей, использования инструмента add-ins , основанный на специфике модулей приложения.например мощь инструмента приложении в логике, в одной сборке и GUI в другой.

В порядке разрешения этих типов архитектуры, add-in roots должен иметь уникальный идентификатор.Add-ins должен ссылаться на этот ID(идентификатор add-in root).Add-in roots так же имеет номер версии, который используется для поддержания логичности между точками расширения, им используемыми, и расширения представляемых add-ins.

Add-in roots могут связывать одну или несколько сборок, которые могут быть выполняемыми или библиотеками. Сложные приложения состоят обычно из нескольких сборок,поэтому важно тщательно определять, что является add-in root, а что нет.

[картика]

В данном примере приложение состоит из 2-х файлов: консольного и графического приложения.Приложение определяет 2 add-in roots:

-Логический корень add-in содержит 2 сборки:Logic.dll and LogicHelper.dll. - GUI add-in root содержит только GUI библиотеку.

Есть 2 основные причины включать сборку в add-in root:

-Сборка определяет несколько классов или интерфейсов для применения add-ins. -Сборке необходимо загрузить остальные сборки add-in root.

Mono.Addins обеспечивает несколько путей декларирования add-in roots и сборок, связывающих их. Это объясняет деталь описания Add-ins и Add-in Hosts секцию, но в кратце, существуют 3 способа:

- Создание файла add-in manifest (XML файл с расширением .addin). - Создание файла add-in manifest и вставка сборок в ресурс. -Использование [assembly:AddinRoot] атрибутов для сборок.

В первом и во втором случае, секция Runtime в manifest может использовать ссылку на сборки, включенных в add-in root. Во втором и третьем случае, различные сборки могут ссылаться на используемые атрибуты [assembly:AddinAssemblyInclude].

Add-in roots обычно имеют главный файл. Когда используется одиночный манифест, главным файлом является манифест. Когда же используется манифест включенный в сборку, или использует атрибут [AddinRoot], главный файл сборки. Только главный файл может включать другие файлы в add-in root.


Add-ins

Add-ins во многом схожи с add-in roots, потому что add-in могут так же себя вести как add-in hosts для разных add-ins. Таким образом, add-ins могут содержать несколько сборок и других файлов,и они могут определить использование отдельных манифестов, и встроенных манифестов или применить атрибуты [assembly:Addin] для данных сборок.

Данная диагрмма отображает add-in сборки и определенный другими add-in:

Add-in roots и add-ins описывают использование разных Add-in моделей описания, но они обходятся разными инструментами. Add-in root assemblies загружают applications hosts использу "регулярные" сборки, пока add-ins are динамично обнаруженные и загруженные add-in инструментом.

Extensible libraries Когда add-in root помещается в библиотеку, в результате мы получаем библиотеку расширения. Правильно в этом случае правильно инкапсулировать подход точек расширенпия к библиотеке.

Таким образом, библиотека будет выглядеть как любая другая библиотека,и любое приложение будет иметь возможность использовать ее как любую другую библиотеку.

Mono.Addins поддерживает несколько одинковых копий add-in root в разных местах. Когда загружается add-in root, the add-in engine будет заботитья о загрузке надстройки для данной версии и включит ее в нее..

Например, допустим, кто-то реализующей общую библиотеку для разбора файлы с исходным кодом называется NParser. NParser обеспечит:

- Общий API для разбора файлов. - Точка расширения для использования надстроек для добавления поддержки новых языков.

Any application might be able to use NParser by just linking to it and distributing it as a private assembly, or using it from the GAC. In this case, add-ins for the library would be loaded from the global registry, unless the application specified a different add-in registry.


Description of Add-ins and Add-in Roots

Every add-in and add-in root has to provide a description of the extensibility elements it provides. There are two ways of doing this:

   * Using custom attributes: Mono.Addins provides several attributes which can be used to mark classes as extensions or extension points. Attributes can also be used to declare add-in information and dependencies.
   * Using an add-in manifest: a manifest is an XML description of an add-in. Attributes are very easy to use, but not all extensibility features that Mono.Addins provides can be expressed using attributes. Any declaration that can be done using custom attributes can also be done in a manifest, but not everything that can be declared in a manifest can also be expressed using custom attributes. Manifests can be deployed as standalone files, or they can be embedded as a resource in assemblies. Manifest files are identified by their extension, which must be ".addin" or ".addin.xml". 

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.

As you can see from the previous examples, the description of an add-in root looks similar to the description of an add-in. In fact, from the point of view of the add-in engine, add-ins and add-in roots are almost the same, so they use the same description model.

The following sections describe in detail all information that can be included in an add-in or add-in root description. The term add-in is used generically in this chapter to refer to add-ins and add-in roots, unless specifically differenced.