Создание приложения с поддержкой плагинов

0

В этой статье описан пример, как создать приложение с поддержкой плагин-архитектуры.

Итак, создает новый проект (Приложение Windows Forms), назовем его «PluginDemo«. После создания проекта переименовываем форму в «FrmMain«, бросаем на форму «ListView«, обзываем его «lvPluginsList«, устанавливаем свойство «View» в «Details«, добавляем 3 колонки (столбца): «Имя плагина», «Описание», «Версия». Думаю, уже догадались, что в этом «ListView» будут выводиться подключенные плагины.

Теперь приступим к написаю интерфейса для будущих плагинов (должны же мы знать, как с ними «общаться»). В обозревателе решений клацаем правой кнопкой мыши по решению «PluginDemo«, выбираем «Добавить» => «Создать проект«.

В списке выбираем «Библиотека классов«, указываем имя — «PlugIn«. Переименовываем «Class1.cs» в «Interfaces.cs» . Открываем этот файл, убираем пустой класс, который создался автоматически и добавляем:

public interface IPlugin
{
	string PluginName { get; } // имя плагина
	string DisplayPluginName { get; } // имя плагина, которое отображается
	string PluginDescription { get; } // описание плагина
	string Author { get; } // имя автора
	int Version { get; } // версия
	IPluginHost Host { get; set; } // ссылка на главную форму
 
	void Show(); // отображает форму
}
public interface IPluginHost
{
	bool Register( IPlugin plug );
}

У всех плагинов должен быть реализован интерфейс, который мы создали выше.
При загрузке плагинов и добавлении их в список мы будет получать значения следующих полей плагина: «DisplayPluginName«, «PluginDescription» и «Version«.
Когда пользователь будет выбирать в списке плагинов нужный ему плагин, то программа будет вызывать метод «Show()» выбранного плагина, в нем плагин может показать свою форму и т.п.
Кстати, не забудьте добавить наследование интерфейса «IPluginHost» главной форме:

public partial class FrmMain : Form, IPluginHost

Также нужно реализовать метод «Register( IPlugin plug )«:

public bool Register( IPlugin plug )
{
	return true;
}

Приступим к написанию плагинов. Снова добавьте новый проект («Библиотека классов«), назовите ее «Plugin1«. После создания проекта нажмите правой клавишей на «References«, выберите «Добавить ссылку…«, в открывшемся окне справа выберите «Решение» => «Проекты«, потом поставьте галочку напротив «PlugIn«.

Добавили мы ссылку на нашу библиотеку, где хранится интерфейс для наших плагинов. Нужно этот интерфейс реализовать в первом плагине (и остальных, естественно), но немного позже. Сейчас нужно добавить форму первому плагину. Снова, в обозревателе решений, нажимаем правой клавишей на «Plugin1«, выбираем «Добавить» => «Форма Windows«, называем ее «FrmP1Main«. Бросаем на форму «TextBox«, обзываем его «tbInfo«,  свойство «Multiline» переключаем в «True«.
Далее открываем код нашей формы, добавляем:

using PlugIn;

Нашему классу «frmP1Main» добавляем поле «plug» типа «IPlugin«:

IPlugin _plug;

Конструктору нашей формы добавляем параметр «IPlugin plug» и в теле конструктора присваиваем параметр полю «_plug», т.е. выйдет такое:

public FrmP1Main( IPlugin plug )
{
	InitializeComponent();
	this._plug = plug;
}

Теперь добавляем обработчик события «Load» нашей форме (нажимаем на форму, с окне «Свойства» нажимаем на значок молнии, два раза клацаем по пункту «Load«; либо двойной щелчок на форме):

private void FrmP1Main_Load( object sender, EventArgs e )
{
	this.tbInfo.AppendText( this._plug.Author + "\r\n" );
	this.tbInfo.AppendText( this._plug.DisplayPluginName + "\r\n" );
	this.tbInfo.AppendText( this._plug.PluginDescription + "\r\n" );
	this.tbInfo.AppendText( this._plug.PluginName + "\r\n" );
	this.tbInfo.AppendText( this._plug.Version + "\r\n" );
}

Думаю, все понятно: во время загрузки формы в «tbInfo» будет добавлена информация о плагине.

Настало время реализовать интерфейс в плагине. Переименовываем файл первого плагина «Class1.cs» в «PlugIn«. Удаляем пустой класс и добавляем следующий код:

public class PlugIn : IPlugin
{
	private string _PluginName = "Plugin1";
	private string _DisplayPluginName = "Первый плагин";
	private string _PluginDescription = "Описание первого плагина";
	private string _Author = "Dev";
	private int _Version = 100;
	IPluginHost _Host;
 
	public void Show()
	{
		frmP1Main frm = new frmP1Main( this );
		frm.ShowDialog();
	}
 
	public IPluginHost Host
	{
		get { return _Host; }
		set
		{
			_Host = value;
			_Host.Register( this );
		}
	}
 
	public string PluginName
	{
		get
		{
			return _PluginName;
		}
	}
 
	public string DisplayPluginName
	{
		get
		{
			return _DisplayPluginName;
		}
	}
 
	public string PluginDescription
	{
		get
		{
			return _PluginDescription;
		}
	}
 
	public string Author
	{
		get
		{
			return _Author;
		}
	}
 
	public int Version
	{
		get
		{
			return _Version;
		}
	}
}

В коде выше реализованы методы и поля интерфейса «IPlugin«, также добавлены свои поля.
Надеюсь, еще не забыли о том, что когда пользователь будет выбирать нужный ему плагин в главном приложении, то наше приложение будет вызывать метод «Show()«, в котором создается экземпляр формы плагина и показывается пользователю.

Второй плагин попробуйте реализовать сами (в конце статьи есть исходник :)).

Возвратимся к главному приложению (PluginDemo). Плагины уже есть, а вот их загрузки нет Сейчас исправим. Добавьте главному приложению ссылку на «PlugIn» (выше есть пример; также подключите с помощью using), далее добавьте поле «_plugins«:

List<IPlugin> _plugins;

Создадим метод «LoadPlugins( string path )«, в качестве параметра будет передаваться путь к папке, где находятся наши плагины (у нас они будут находиться в папке с программой):

private void LoadPlugins( string path )
{
	string[] pluginFiles = Directory.GetFiles( path, "*.dll" );
	this._plugins = new List<IPlugin>();
 
	foreach ( string pluginPath in pluginFiles )
	{
		Type objType = null;
		try
		{
			// пытаемся загрузить библиотеку
			Assembly assembly = Assembly.LoadFrom( pluginPath );
			if ( assembly != null )
			{
				objType = assembly.GetType( Path.GetFileNameWithoutExtension( pluginPath ) + ".PlugIn" );
			}
		}
		catch
		{
			continue;
		}
		try
		{
			if ( objType != null )
			{
				this._plugins.Add( (IPlugin)Activator.CreateInstance( objType ) );
				this._plugins[ this._plugins.Count - 1 ].Host = this;
			}
		}
		catch
		{
			continue;
		}
	}
}

Собственно, ищем все .dll в папке с программой (проверяя на наличие нашего «PlugIn«) и добавляем в список.

Теперь добавим метод, который будет добавлять подключенные плагины в «ListView«:

private void AddPluginsItems()
{
	this.lvPlugins.Items.Clear();
	foreach ( IPlugin plugin in this._plugins )
	{
		if ( plugin == null )
		{
			continue;
		}
		this.lvPlugins.Items.Add( plugin.DisplayPluginName );
		this.lvPlugins.Items[ this.lvPlugins.Items.Count - 1 ].SubItems.Add( plugin.Version.ToString() );
		this.lvPlugins.Items[ this.lvPlugins.Items.Count - 1 ].SubItems.Add( plugin.Author );
	}
}

Пробегаемся по списку плагинов и добавляем в «lvPlugins» имя, версию и автора плагинов.

Добавляем методы «LoadPlugins()» и «AddPluginsItems()» в обработчик события «Load» формы:

private void FrmMain_Load( object sender, EventArgs e )
{
	this.LoadPlugins( Application.StartupPath );
	this.AddPluginsItems();
}

Добавляем еще один обработчик события «DoubleClick» для «lvPlugins«:

private void lvPlugins_DoubleClick( object sender, EventArgs e )
{
	if ( this.lvPlugins.SelectedItems.Count > 0 )
	{
		int selectedIndex = this.lvPlugins.SelectedItems[ 0 ].Index;
		this._plugins[ selectedIndex ].Show();
	}
}

Здесь мы проверяем: есть ли выделенные элементы, если есть — получаем индекс первого выделенного и вызываем метод «Show()» выбранного плагина.

В общем, всё 

Должно получится что-то типа такого:

Исходник:

Источник: https://www.softez.pp.ua/

0
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
Авторизация
*
*
Регистрация
*
*
*
Пароль не введен
*
Генерация пароля
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x