Использование плагинов в приложении

Плагины используются для того, чтобы динамически расширять функционал приложения без повторной перекомпиляции,.

Плагин - это модуль, к которому может обращаться приложение для выполнения каких-либо действий. Отличие от обычных модулей(например, dll) заключается в том, что хост-программа изначально ничего не знает об этих модулях, и узнаёт о них только в момент их инсталляции. Для реализации плагинов в среде .net используется механизм, который называется "рефлексия" (см., например http://msdn.microsoft.com/ru-ru/library/ms173183.aspx, http://www.intuit.ru/department/pl/csharp20/10/ и http://ru.wikipedia.org/wiki/Отражение_(программирование)) из пространства System.Reflection.

Для реализации плагинной системы необходимо выполнить следующие шаги:
  • Определить общий интерфейс, который будет использоваться всеми плагинами
interface IPlugin
{
    string GetData();
    void SetData(string s);
}
  • Реализовать данный интерфейс для каждой библиотеки(плагина)
Пример кода plugin.dll
public class Test:IPlugin
{
    public string GetData()
    {
        //Получение данных
    }
    public void SetData(string s)
    {
        //Добавление данных
    }
}
  • Выполнить загрузку плагинов из указанного каталога
Важно отметить что сборки загруженные в основной домен приложения выгрузить без выгрузки основного домена нельзя. Эту проблему можно обойти используя дополнительные домены.

Простейшей пример загрузки плагинов.
        /// <summary>
        /// Загрузка плагина
        /// </summary>
        /// <param name="path">Путь к каталогу</param>
        /// <param name="moduleName">Имя библиотеки с плагином</param>
        public static IPlugin LoadPlugin(string path, string moduleName)
        {
            Assembly lib = null;
            IPlugin plugin = null;
            try
            {
                //если сборка уже загружена в основной домен, не пытаемся ее загрузить повторно
                if ((lib = AppDomain.CurrentDomain.GetAssemblies().Select(x => x).Where(x => String.Compare(x.ManifestModule.Name, moduleName, true) == 0).FirstOrDefault()) == null)
                    lib = Assembly.LoadFrom(path+moduleName);

                foreach (Type type in lib.GetTypes())
                {
                    //Проверяем реализуют ли объекты библиотеки наш интерфейс
                    if (type.GetInterface("IPlugin")!= null)
                    {
                        plugin = (IPlugin)Activator.CreateInstance(type, null, null);
                    }
                }

            }
            catch (Exception ex)
            {
                //обработка ошибки
            }
            return plugin;
        }
Функция LoadPlugin вернет ссылку на объект загруженный из модуля с плагином. Теперь мы можем работать с ним:
IPlugin plugin= LoadPlugin(@"c:\tmp\","plugin.dll");
if(plugin!=null)
{
    plugin. GetData(); 
}

Дополнительную информацию см. в разделе Reflection в MSDN http://msdn.microsoft.com/ru-ru/library/ms173183.aspx
--
автор: Гетманский Сергей

Last edited Jan 18, 2012 at 11:38 AM by basph, version 11

Comments

No comments yet.