Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Общая схема реализации плагинов, как? 
:(
    Опции темы
Medved
Дата 22.12.2004, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Подскажите общую схему реализации плагинов в своей программе. Какие могутт быть подводные камни?. Планируется это осуществлять для крупного и довольно сложного web-сервиса.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Mad
Дата 22.12.2004, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Мы используем такую схему:

AppDomain.Current.LoadAssembly() для загрузки плагина
потом через Runtime или создаеш обьект класса, или вызываеш static функции

Но есть один минус : выгрузить dll уже нельзя smile


--------------------
user posted image
PM MAIL   Вверх
Medved
Дата 22.12.2004, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



А можно поподробнее?
Добавлено @ 15:09
Я планировал реализовывать через интерфейсы.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Mad
Дата 22.12.2004, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Вот класс для загрузки плагинов
Код

using System;
using System.IO;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Windows.Forms;
using System.Xml;
using System.Collections;

namespace omis
{
/// <summary>
/// Summary description for Loader.
/// </summary>
public class Loader
{
 public Loader()
 {
 }

 public static object LoadModule(string name, object arg)
 {
  Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
  for (int i=0; i<asms.Length; i++)
  {
   Type typ = asms[i].GetType(name, false, true);
   if (typ != null)
   {
    try
    {
     object[] args = new object[1];
     args[0] = arg;
     return typ.InvokeMember(null, BindingFlags.CreateInstance, null, null, args);
    }
    catch (Exception ex)
    {
     omis.console.Console.ReportWarning("omis.Loader", "Failed create instance of "+name, ex.Message+"\r\n"+ex.StackTrace);
    }
   }
  }
  return null;
 }

 public static Type[] GetTypeFromBase(string name)
 {
  ArrayList cach = new ArrayList();
  Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
  for (int i=0; i<asms.Length; i++)
  {
   Type[] tp = asms[i].GetTypes();
   for (int k=0; k<tp.Length; k++)
   {
    if (tp[k].BaseType != null && tp[k].BaseType.ToString().ToLower() == name)
     cach.Add(tp[k]);
   }
  }

  if (cach.Count > 0)
  {
   Type[] ret = new Type[cach.Count];
   for (int i=0; i<cach.Count; i++)
    ret[i] = (Type)cach[i];
   cach.Clear();
   return ret;
  }
  return null;
 }

 public static Type GetModule(string name)
 {
  Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
  for (int i=0; i<asms.Length; i++)
  {
   Type typ = asms[i].GetType(name, false, true);
   if (typ != null)
   {
    return typ;
   }
  }

  string[] sname = name.Split('.');
  string pname = "../libs";
  for (int i=0; i<sname.Length-1; i++)
   pname += "/"+sname[i];
  string fname = pname+"/"+sname[sname.Length-1];

  try
  {
   StreamReader fs = new StreamReader(fname+".cs", System.Text.Encoding.GetEncoding("WINDOWS-1251"));
   string src = fs.ReadToEnd();
   fs.Close();

   CSharpCodeProvider code = new CSharpCodeProvider();
   ICodeCompiler comp = code.CreateCompiler();

   CompilerParameters opt = new CompilerParameters();
   opt.GenerateInMemory = true;
   opt.GenerateExecutable = false;
   opt.OutputAssembly = null; //fname+".dll";
   opt.IncludeDebugInformation = false;
   opt.ReferencedAssemblies.Add("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Xml.dll");
   opt.ReferencedAssemblies.Add("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Windows.Forms.dll");
   opt.ReferencedAssemblies.Add("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.Drawing.dll");
   opt.ReferencedAssemblies.Add("C:\\WINNT\\Microsoft.NET\\Framework\\v1.0.3705\\System.dll");
   CompilerResults res = comp.CompileAssemblyFromSource(opt, src);

   if (res.Errors.Count > 0)
   {
    for (int i=0; i < res.Errors.Count; i++)
     omis.console.Console.ReportWarning("omis.Loader.GetModule", res.Errors[i].ErrorText, fname);
   }
   else
   {
    Type typ = res.CompiledAssembly.GetType(name, true, true);
    if (typ != null)
    {
     return typ;
    }
   }
  }
  catch (Exception ex)
  {
   omis.console.Console.ReportError("omis.Loader.GetModule", ex.Message, fname);
  }
  return null;
 }
}
}


LoadModule() возвращает обьект класса по имени



--------------------
user posted image
PM MAIL   Вверх
Medved
Дата 22.12.2004, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Посмотрел вскольз я на пример, и ИМХО через интерфесы будет более универсально, и к тому же более приближено к пардиаграме ООП. Хотя возможно что я и ошибаюсь. Но в любом случае спасибо!


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Medved
Дата 23.12.2004, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



НИкто никогда не реализовывал механизм плагинов?


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Mad
Дата 23.12.2004, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Pegas
Кстати , сам об этом не думал smile, мой пример применим и к интерфейсам (надо только заменить возвращаемый тип с object на нужный тебе интерфейс). Мы просто приводим возвращаемый обьект к нужному классу (если обьект другого класса .NET генерить Exception).


--------------------
user posted image
PM MAIL   Вверх
arilou
Дата 23.12.2004, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Мои пять копеек smile Для реализации плагинов используется следующий стандартный подход:

1) С помощью интерфейсов определяется стандартная схема взаимодействия плагина с хост-приложением и наоборот. Например, интерфейс дает возможность плагину сообщить, в каком меню, после какого и перед каким элементом он должен появиться

2) Основное приложение при запуске или считывает информацию о том, какие плагины надо загрузить, например, из конфига, или берет все DLL'ки из определенной папки.

3) С помощью Reflection'a из сборок, содержащих плагины, достается информация о том, какой именно класс реализует искомый интерфейс IPlugin

4) С помощью того же Reflection'a создается экземпляр основного класса-плагина. Он приводится к интерфейсу IPlugin, и через него происходит собственно взаимодействие

Хороший пример реализации плагинов используется в среде разработки Sharp Develop. На сайте можно скачать source code и доки, её описывающие.
Добавлено @ 15:48
Цитата(Mad @ 22.12.2004, 14:25)
Но есть один минус : выгрузить dll уже нельзя 

В таких случах плагин грузят в другой домен. Домены выгружать можно, и, кстати, это защищает основное приложение от крэшев в плагинах.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
Mad
Дата 23.12.2004, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Цитата(arilou @ 23.12.2004, 14:46)
В таких случах плагин грузят в другой домен.

Появляються сложности общения с основным приложением (обмен данными)

Цитата(arilou @ 23.12.2004, 14:46)
это защищает основное приложение от крэшев в плагинах.

Для этого просто ставиться свой обработчик Exception (Application.ThreadException)


--------------------
user posted image
PM MAIL   Вверх
arilou
Дата 23.12.2004, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Цитата(Mad @ 23.12.2004, 15:57)
Появляються сложности общения с основным приложением (обмен данными)

В случае, если плагины может разрабатывать треья сторона, их надо изолировать. Я считаю, что потратив сразу некоторое время на создание стандартного мех-ма взаимодействия плагина с основной программой (обертку вокруг CrossDomainDelegate), можно отсечь возможные проблемы в будущем.

Цитата(Mad @ 23.12.2004, 15:57)
Для этого просто ставиться свой обработчик Exception (Application.ThreadException)

Есть exception'ы, которые не ловятся Application.ThreadException. Видел не один раз, особенно в релиз-версии.


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
Mad
Дата 23.12.2004, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Цитата(arilou @ 23.12.2004, 15:38)
Есть exception'ы, которые не ловятся Application.ThreadException. Видел не один раз, особенно в релиз-версии.

Например ?


--------------------
user posted image
PM MAIL   Вверх
arilou
Дата 23.12.2004, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Приложение работает некоторое время (час, 5 минут, пол-дня). Потом вылазит сообщение "Unhandled exception, thread id bla bla, process id bla bla". И всё. Во всех возможных местах стоят обработчики. Детально описать не получится - приложение сложное.
Добавлено @ 17:00
Цитата(Mad @ 22.12.2004, 15:20)
Код

for (int i=0; i<asms.Length; i++)
 {
  Type typ = asms[i].GetType(name, false, true);
  if (typ != null)
  {
   return typ;
  }
 }


Вопрос не по теме - а почему foreach не используешь?


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
Mad
Дата 23.12.2004, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 1
Всего: 19



Цитата(arilou @ 23.12.2004, 15:57)
Потом вылазит сообщение "Unhandled exception, thread id bla bla, process id bla bla".

Это глюк 1.0 (вылетает сама VM) и уже не важно в каком AppDomain это произошло, закрывается все приложение (а иногда и все .NET приложения на тачке smile) в 1.1 вроде такого уже не наблюдается.
Добавлено @ 17:05
Цитата(arilou @ 23.12.2004, 15:57)
а почему foreach не используешь?

Я отот класс писал когда тока начал C# учить (больше технология интересовалла чем особенности языка).
Да и теперь восновном for использую, привычней smile


--------------------
user posted image
PM MAIL   Вверх
Medved
Дата 28.12.2004, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Цитата(Mad @ 23.12.2004, 20:02)
Я отот класс писал когда тока начал C# учить (больше технология интересовалла чем особенности языка).
Да и теперь восновном for использую, привычней smile


Я наоборот стараюсь реализовывать интерфейсы IComparable и IComparer в своих пользовательских классах, чтобы можно было применять к массивам этих объектова цикл forech. Чертовски удобно.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
arilou
Дата 28.12.2004, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Великий МунаБудвин
****


Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск

Репутация: 21
Всего: 61



Цитата(Pegas @ 28.12.2004, 00:26)
Я наоборот стараюсь реализовывать интерфейсы IComparable и IComparer в своих пользовательских классах, чтобы можно было применять к массивам этих объектова цикл forech. Чертовски удобно.

А что, ты не наследушь классы коллекций от стандартных (например, ArrayList) ?


--------------------
user posted imageuser posted image
PM WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0551 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.