Расширение функционала плагинов в плагинном приложении
От: nomicon Россия  
Дата: 08.07.09 14:34
Оценка:
Требуется написать плагинное приложение .NET C#.

Примерная архитектура следующая:

1. Есть библиотека типов (интерфейсов) на которую имеем ссылку в главном приложении и в каждом из плагинов.
2. При загрузке плагина основным приложением осуществляем создание наших "плагинных" классов и приведение типов к интерфейсам из библиотеки типов.
3. Работаем с классами из плагинов через интерфейсы.

Вроде всё выглядит логично и понятно, но есть следующая заковырка — нет возможности расширить "функционал" плагинов.
Т.е. понадобилось, например добавить метод в какой-либо из интерфейсов (например передачу доболнительных настроек). В остальном же новый плагин предоставляет тот же функционал, что и предыдущие плагины. Данная ситуация на 99% возникнет т.к. изначально практически невозможно представить весь возможный функционал плагинов.

Вот и возникает вопрос как решать данную проблему?
Видятся следующие варианты:
Вариант 1: Пытаться делать интерфейсы библиотеки типов максимально универсальными, т.е. передавать параметры в виде object, настройки в виде XML и т.п..
Вариант 2 (усложненный 1-й): делать Классы-коллекции (контейнеры) функциональных классов в плагинах реализующих простые интерфейсы (1-3 метода) и расширять функциональность плагина за счет добавления нового элемента-класса в класс-коллекцию внутри плагина (понятно написал?).
Вариант 3: При расширении функциональности делать новую библиотеку типов, с новыми интерфейсами и для работы старых плагинов реализовывать механизм преобразования старого интерфейса в новый с "пустым" функционалом в новых методах.

Больше в голову особо ничего не приходит. Если кто сталкивался, то каким образом реализовывал подобные вещи?
Дайти ссылки, у кого есть, на примеры проектов или кода с архитектурой позволяющей решать указанные проблемы (на Янус можно не давать , уже смотрел хотелось бы посмотреть ещё варианты).





09.07.09 10:50: Перенесено из '.NET'
Re: Расширение функционала плагинов в плагинном приложении
От: baranovda Российская Империя  
Дата: 08.07.09 15:21
Оценка:
Здравствуйте, nomicon, Вы писали:

N>Больше в голову особо ничего не приходит. Если кто сталкивался, то каким образом реализовывал подобные вещи?

N>Дайти ссылки, у кого есть, на примеры проектов или кода с архитектурой позволяющей решать указанные проблемы (на Янус можно не давать , уже смотрел хотелось бы посмотреть ещё варианты).

Поковыряйте архитектуру Microsoft Smart Client Software Factory.
Re[2]: Расширение функционала плагинов в плагинном приложени
От: Аноним  
Дата: 08.07.09 17:44
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Здравствуйте, nomicon, Вы писали:


B>Поковыряйте архитектуру Microsoft Smart Client Software Factory.


Чесно говоря даже близко не нашел там ничего подходящего для решения моего вопроса.
Повторюсь, необходимы примеры работы с плагинами и варианты решения описанной в посте проблемы.
Re[3]: Расширение функционала плагинов в плагинном приложени
От: baranovda Российская Империя  
Дата: 08.07.09 18:52
Оценка: 2 (1)
Здравствуйте, Аноним, Вы писали:

А>Чесно говоря даже близко не нашел там ничего подходящего для решения моего вопроса.

А>Повторюсь, необходимы примеры работы с плагинами и варианты решения описанной в посте проблемы.

Плохо читали.
В архитектуре SCSF загрузчик-bootstrapper инициализирует корневой контейнер (WorkItem), выполняет поиск модулей (плагинов), ищет точку входа в каждом модуле и запускает его на исполнение. В свою очередь модули конструируют свои WorkItems и подключают его к корневому контейнеру. Есть функционал навигации по дереву контейнеров. Вот вам и механизм коммуникации плагинов.
Что касается ваших трех решений, то ни один из них не гарантирует расширяемость, поскольку они все завязаны на архитектуру модульного решения. В SCSF предлагается другой подход — сервисы ничего не знают о плагинах, а плагин является просто контейнером сервисов. Контейнеры включают в себя локаторы, которые умеют опрашивать другие контейнеры дерева на предмет поддержки интерфейса того или иного сервиса. Более новые версии интерфейса обычно наследуют от более старых. Вот вам и механизм версионности.

То же самое можно реализовать при помощи других DI-контейнеров, например, Unity. SCSF заточена под десктоп.
Re: Расширение функционала плагинов в плагинном приложении
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.07.09 06:56
Оценка: 3 (1)
Здравствуйте, nomicon, Вы писали:

N>Требуется написать плагинное приложение .NET C#.


N>Примерная архитектура следующая:


N>1. Есть библиотека типов (интерфейсов) на которую имеем ссылку в главном приложении и в каждом из плагинов.

N>2. При загрузке плагина основным приложением осуществляем создание наших "плагинных" классов и приведение типов к интерфейсам из библиотеки типов.
N>3. Работаем с классами из плагинов через интерфейсы.

N>Вроде всё выглядит логично и понятно, но есть следующая заковырка — нет возможности расширить "функционал" плагинов.

N>Т.е. понадобилось, например добавить метод в какой-либо из интерфейсов (например передачу доболнительных настроек). В остальном же новый плагин предоставляет тот же функционал, что и предыдущие плагины. Данная ситуация на 99% возникнет т.к. изначально практически невозможно представить весь возможный функционал плагинов.

N>Вот и возникает вопрос как решать данную проблему?

N>Видятся следующие варианты:
N>Вариант 1: Пытаться делать интерфейсы библиотеки типов максимально универсальными, т.е. передавать параметры в виде object, настройки в виде XML и т.п..
N>Вариант 2 (усложненный 1-й): делать Классы-коллекции (контейнеры) функциональных классов в плагинах реализующих простые интерфейсы (1-3 метода) и расширять функциональность плагина за счет добавления нового элемента-класса в класс-коллекцию внутри плагина (понятно написал?).
N>Вариант 3: При расширении функциональности делать новую библиотеку типов, с новыми интерфейсами и для работы старых плагинов реализовывать механизм преобразования старого интерфейса в новый с "пустым" функционалом в новых методах.

N>Больше в голову особо ничего не приходит. Если кто сталкивался, то каким образом реализовывал подобные вещи?

N>Дайти ссылки, у кого есть, на примеры проектов или кода с архитектурой позволяющей решать указанные проблемы (на Янус можно не давать , уже смотрел хотелось бы посмотреть ещё варианты).


Откажитесь от мысли "один плагин — один интерфейс" и жить станет легче.
Пусть каждый плагин требует от основного приложения некоторыйнабор интерфейсов (импортов) и экспортирует некоторые интерфейсы.
Такая архитектура заложена в MEF и мне видится самой удачной для плагинов.

Ограничение только одной — приложение должно доверять плагинам, изолировать их при такой архитектуре будет проблематично.
Re[4]: Расширение функционала плагинов в плагинном приложени
От: nomicon Россия  
Дата: 09.07.09 08:23
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Плохо читали.

B>В архитектуре SCSF загрузчик-bootstrapper инициализирует корневой контейнер (WorkItem), выполняет поиск модулей (плагинов), ищет точку входа в каждом модуле и запускает его на исполнение. В свою очередь модули конструируют свои WorkItems и подключают его к корневому контейнеру. Есть функционал навигации по дереву контейнеров. Вот вам и механизм коммуникации плагинов.
B>Что касается ваших трех решений, то ни один из них не гарантирует расширяемость, поскольку они все завязаны на архитектуру модульного решения. В SCSF предлагается другой подход — сервисы ничего не знают о плагинах, а плагин является просто контейнером сервисов. Контейнеры включают в себя локаторы, которые умеют опрашивать другие контейнеры дерева на предмет поддержки интерфейса того или иного сервиса. Более новые версии интерфейса обычно наследуют от более старых. Вот вам и механизм версионности.

B>То же самое можно реализовать при помощи других DI-контейнеров, например, Unity. SCSF заточена под десктоп.


Читал нормально, но видимо немного не то — нужен не совсем SCSF, а скорее по следующим ключевым словам "Architecting Composite Smart Clients Using SCSF" а сам SCSF это набор инструментов, поэтому и не смог найти нужное мне. Но все равно спасибо.
Re[2]: Расширение функционала плагинов в плагинном приложени
От: nomicon Россия  
Дата: 09.07.09 08:52
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Откажитесь от мысли "один плагин — один интерфейс" и жить станет легче.

G>Пусть каждый плагин требует от основного приложения некоторыйнабор интерфейсов (импортов) и экспортирует некоторые интерфейсы.
G>Такая архитектура заложена в MEF и мне видится самой удачной для плагинов.

G>Ограничение только одной — приложение должно доверять плагинам, изолировать их при такой архитектуре будет проблематично.


Никто и не говорил про "один плагин — один интерфейс". Я так понимаю идея состоит в том, чтобы плагин говорил главному приложению какие он реализует интерфейсы и главная прога дергала нужные ей, так?.
Тогда какова идея реализации новых интерфейсов?
1. Создавать новый интерфейс и классом плагина релизовывать старый интерфейс + новый(дополнение к старому). Тогда придется в основном приложении объединять интерфейсы в 1, по-моему так.
2. Делать новый интерфейс — наследник старого и делать адаптер с пустыми методами?
3. Главная прога работает с кучей интерфейсов — т.е. новый интерфейс — новая куча враждебного для ООП кода
со switch и т.п.
В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.

И большая просьба, если есть у кого ссылки на удачные плагинные движки — киньте сюда если не сложно.
Re[3]: Расширение функционала плагинов в плагинном приложени
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.07.09 09:22
Оценка:
Здравствуйте, nomicon, Вы писали:

N>Здравствуйте, gandjustas, Вы писали:


G>>Откажитесь от мысли "один плагин — один интерфейс" и жить станет легче.

G>>Пусть каждый плагин требует от основного приложения некоторыйнабор интерфейсов (импортов) и экспортирует некоторые интерфейсы.
G>>Такая архитектура заложена в MEF и мне видится самой удачной для плагинов.

G>>Ограничение только одной — приложение должно доверять плагинам, изолировать их при такой архитектуре будет проблематично.


N>Никто и не говорил про "один плагин — один интерфейс". Я так понимаю идея состоит в том, чтобы плагин говорил главному приложению какие он реализует интерфейсы и главная прога дергала нужные ей, так?.

N> Тогда какова идея реализации новых интерфейсов?
Опять таже проблема, вы считаете что интефейсов для расширения будет небольшое количество и при развитии программы будут появляться новые версии этих интерфейсов.
Если же у вас на каждую потенциальную точку расширения будут небольшие интерфейсы (возможно такие обобщенные как Func<T>), то вам очень редко понадобится расширять существующие, в основном только добавлять новые.

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

N>В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.

Это не проблема, надо умень делать интерфейсы.
Re[3]: Расширение функционала плагинов в плагинном приложени
От: baranovda Российская Империя  
Дата: 09.07.09 09:26
Оценка:
Здравствуйте, nomicon, Вы писали:

N>3. Главная прога работает с кучей интерфейсов — т.е. новый интерфейс — новая куча враждебного для ООП кода

N>со switch и т.п.
N>В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.

Проблема версионности сервисов никак не связана с проблемой плаггед-приложений и уже давно завернута в паттерны.


//
// Assembly My.Service1_0.dll
//

interface IService1_0
{
   void Foo();
}

class Service1_0 : IService1_0
{
   public virtual void Foo() { print "Version 1.0"; }
}

class Service : Service1_0
{

}

//
// Assembly My.Service2_0.dll
//
interface IService2_0 : IService1_0
{
  void Bar();
}

class Service2_0 : Service1_0, IService2_0
{
   override void Foo() { print "Improved version 2.0"; }
   void Bar();
}

class Service: Service2_0
{

}


Клиент:


Service service = Activator.CreateInstance(typeof(Service));
bool version1_0 = (service as IService1_0) != null;
bool version2_0 = (service as IService2_0) != null;
Re: Расширение функционала плагинов в плагинном приложении
От: Аноним  
Дата: 09.07.09 11:57
Оценка:
Здравствуйте, nomicon, Вы писали:

Можно вопрос: как вы поступаете когда нужно предоставить информацию о плагине (название, описание, некие характеристики, etc)? Вы добавляете метод в интерфейс плагина для получения такой информации или для этого есть специальный атрибут который будет применен к конкретному классу плагина? Что-то типа:

    // общая сборка с описаниями типов
    [AttributeUsage(AttributeTargets.Class)]
    public class PluginInfoAttribute : Attribute
    {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public string Description { get; set; }
        public bool SupportsFeature1 { get; set; }
        public bool SupportsFeature2 { get; set; }
        public bool SupportsFeature3 { get; set; }
    }

    // сборка конкретного плагина    
    [PluginInfo(Name = ...)]
    public class Plugin : IPlugin
    {...}

Как вообще правильней?
Re[2]: Расширение функционала плагинов в плагинном приложени
От: Sergey T. Украина http://overstore.codeplex.com
Дата: 09.07.09 16:38
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, nomicon, Вы писали:


А>Можно вопрос: как вы поступаете когда нужно предоставить информацию о плагине (название, описание, некие характеристики, etc)? Вы добавляете метод в интерфейс плагина для получения такой информации или для этого есть специальный атрибут который будет применен к конкретному классу плагина? Что-то типа:


А>
А>    // общая сборка с описаниями типов
А>    [AttributeUsage(AttributeTargets.Class)]
А>    public class PluginInfoAttribute : Attribute
А>    {
А>        public string Name { get; set; }
А>        public string DisplayName { get; set; }
А>        public string Description { get; set; }
А>        public bool SupportsFeature1 { get; set; }
А>        public bool SupportsFeature2 { get; set; }
А>        public bool SupportsFeature3 { get; set; }
А>    }

А>    // сборка конкретного плагина    
А>    [PluginInfo(Name = ...)]
А>    public class Plugin : IPlugin
А>    {...}
А>

А>Как вообще правильней?
Лучше сделать как проще, а именно, добавить в интерфейс плагина метод, который будет возвращать указанную вами структуру данных.
There is no such thing as the perfect design.
Re: Расширение функционала плагинов в плагинном приложении
От: sto Украина http://overstore.codeplex.com
Дата: 09.07.09 16:49
Оценка:
Здравствуйте, nomicon, Вы писали:

N>Требуется написать плагинное приложение .NET C#.


N>Примерная архитектура следующая:


N>1. Есть библиотека типов (интерфейсов) на которую имеем ссылку в главном приложении и в каждом из плагинов.

N>2. При загрузке плагина основным приложением осуществляем создание наших "плагинных" классов и приведение типов к интерфейсам из библиотеки типов.
N>3. Работаем с классами из плагинов через интерфейсы.

N>Вроде всё выглядит логично и понятно, но есть следующая заковырка — нет возможности расширить "функционал" плагинов.

N>Т.е. понадобилось, например добавить метод в какой-либо из интерфейсов (например передачу доболнительных настроек). В остальном же новый плагин предоставляет тот же функционал, что и предыдущие плагины. Данная ситуация на 99% возникнет т.к. изначально практически невозможно представить весь возможный функционал плагинов.

N>Больше в голову особо ничего не приходит. Если кто сталкивался, то каким образом реализовывал подобные вещи?

N>Дайти ссылки, у кого есть, на примеры проектов или кода с архитектурой позволяющей решать указанные проблемы (на Янус можно не давать , уже смотрел хотелось бы посмотреть ещё варианты).

Чем четче определен контракт для плагина, тем лучше. Вы должны четко знать, что должен делать плагин, что, но не как. Никакого "расширения функционала" плагинов делать не стоит, иначе это обернется кошмарным кодом. Никаких дополнительных настроек плагин передавать не должен. Как будет их обрабатывать приложение-хост? Откуда оно узнает о них?
Приведите пожалуйста пример расширения функционала, чего вы хотите добится, мне например не совсем ясно.
There is no such thing as the perfect design.
Re[2]: Расширение функционала плагинов в плагинном приложени
От: Аноним  
Дата: 09.07.09 16:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, nomicon, Вы писали:


А>Можно вопрос: как вы поступаете когда нужно предоставить информацию о плагине (название, описание, некие характеристики, etc)? Вы добавляете метод в интерфейс плагина для получения такой информации или для этого есть специальный атрибут который будет применен к конкретному классу плагина? Что-то типа:


А>
А>    // общая сборка с описаниями типов
А>    [AttributeUsage(AttributeTargets.Class)]
А>    public class PluginInfoAttribute : Attribute
А>    {
А>        public string Name { get; set; }
А>        public string DisplayName { get; set; }
А>        public string Description { get; set; }
А>        public bool SupportsFeature1 { get; set; }
А>        public bool SupportsFeature2 { get; set; }
А>        public bool SupportsFeature3 { get; set; }
А>    }

А>    // сборка конкретного плагина    
А>    [PluginInfo(Name = ...)]
А>    public class Plugin : IPlugin
А>    {...}
А>

А>Как вообще правильней?

Это уже вопрос практической реализации, оба способа правильные.
Используя атрибут нет необходимости создавать экземпляр класса плагина для получения информации о нём.

Исползуя же дополнительный информационный интерфейс:
public class Plugin : IPlugin, IPluginDescription
{...}

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

Вобщем оба способа вполне приемлемы.
Re[4]: Расширение функционала плагинов в плагинном приложени
От: Аноним  
Дата: 09.07.09 17:11
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Здравствуйте, nomicon, Вы писали:


N>>3. Главная прога работает с кучей интерфейсов — т.е. новый интерфейс — новая куча враждебного для ООП кода

N>>со switch и т.п.
N>>В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.

B>Проблема версионности сервисов никак не связана с проблемой плаггед-приложений и уже давно завернута в паттерны.


B>

B>//
B>// Assembly My.Service1_0.dll
B>//

B>interface IService1_0
B>{
B>   void Foo();
B>}

B>class Service1_0 : IService1_0
B>{
B>   public virtual void Foo() { print "Version 1.0"; }
B>}

B>class Service : Service1_0
B>{

B>}

B>//
B>// Assembly My.Service2_0.dll
B>//
B>interface IService2_0 : IService1_0
B>{
B>  void Bar();
B>}

B>class Service2_0 : Service1_0, IService2_0
B>{
B>   override void Foo() { print "Improved version 2.0"; }
B>   void Bar();
B>}

B>class Service: Service2_0
B>{

B>}

B>


B>Клиент:


B>

B>Service service = Activator.CreateInstance(typeof(Service));
B>bool version1_0 = (service as IService1_0) != null;
B>bool version2_0 = (service as IService2_0) != null;

B>


вот потом и начинаются всевозможные switch, if и т.п. в основном приложении (читай враждебный ООП код). Преобразовывать всё надо к IService2_0, чтобы ядро основной проги работало с одной версией интерфейса — последней.
Соответственно надо приводить IService1_0 к IService2_0, а это можно сделать только через класс-адаптер — т.е. мой вариант 3 решения проблемы из корневого поста.
Re[4]: Расширение функционала плагинов в плагинном приложени
От: Аноним  
Дата: 09.07.09 17:20
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Опять таже проблема, вы считаете что интефейсов для расширения будет небольшое количество и при развитии программы будут появляться новые версии этих интерфейсов.

G>Если же у вас на каждую потенциальную точку расширения будут небольшие интерфейсы (возможно такие обобщенные как Func<T>), то вам очень редко понадобится расширять существующие, в основном только добавлять новые.
Это вариант 1 из корневого поста, разве что дженерики там не упомянул.

G>Если уж нужно расширить интерфейс, то создается наследник с суффиксом 2 в конце, а в коде приложения появляется if, который при необходимости вызывает метод расширенного интерфейса.

С использованием if мы пускаем побоку всю прелесть ООП, и имея скажем 10 новых версий того или иного интерфейса придется делать 10 if? И здравствуй старое доброе структурное программирование?
N>>В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.
G>Это не проблема, надо умень делать интерфейсы.
Re: Расширение функционала плагинов в плагинном приложении
От: nomicon Россия  
Дата: 09.07.09 17:22
Оценка:
Вобщем просьба — если есть готовые движки с исходниками для работы с плагинами (как интерфейсными так и функциональными) просьба дать ссылки.
Re[5]: Расширение функционала плагинов в плагинном приложени
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.07.09 17:25
Оценка:
Здравствуйте, Аноним, Вы писали:

G>>Если уж нужно расширить интерфейс, то создается наследник с суффиксом 2 в конце, а в коде приложения появляется if, который при необходимости вызывает метод расширенного интерфейса.

А>С использованием if мы пускаем побоку всю прелесть ООП, и имея скажем 10 новых версий того или иного интерфейса придется делать 10 if? И здравствуй старое доброе структурное программирование?
Если будет 10 новых версий это значит что изначально была допущена ошибка в проектировании интерфейсов.
Парочка новых версий для пары интерфейсов — вполне нормальная ситуация, и пара ифов гораздо выгоднее чем пытаться поддерживать труЪ ООП постоянно.
А где ты тут увидел структурное программирование?
Re[2]: Расширение функционала плагинов в плагинном приложени
От: nomicon Россия  
Дата: 09.07.09 17:56
Оценка:
Здравствуйте, sto, Вы писали:

sto>Чем четче определен контракт для плагина, тем лучше. Вы должны четко знать, что должен делать плагин, что, но не как. Никакого "расширения функционала" плагинов делать не стоит, иначе это обернется кошмарным кодом. Никаких дополнительных настроек плагин передавать не должен. Как будет их обрабатывать приложение-хост? Откуда оно узнает о них?

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

Вот с тем как делать тоже не всё понятно на 100%.
Опишу кратко суть задачи: есть крупная организация, в которой функционирует несколько десятков пользовательских приложений и не меньше админских.
Необходимо засунуть их в один Шелл для устранения некоторой стохастичности их функционировании и решения следующих проблем:
1. Хранение настроек в центральной БД, чтобы для конкретного пользователя настройки приложения на каждом ПК были одинаковыми.
2. Менять системные настройки для всех в одном месте.
3. Простой способ обновления плагинов.
4. Система разграничения доступа разных пользователей к разным приложениям.
5. Унификация функционирующих в системе сообщений (читай файлов) невозможность доступа к ним не из Шелла, посредством хранения в БД.
.... и т.п.

Соответственно вопрос — как определить что делать например для
a) редактора базы клиентов
b) прога обработки корреспонденции
с) система автоматической генерации ответов клиентам
d) внутренний документооборот

причем замечу, что например "внутренний документ" и "письмо клиента" в целом для системы одно и то же, состоящее из XML заголовка и тела сообщения (doc или msg) содержащееся в 1 таблице БД (SQL 2008 File Storage) и таких видов сообщений куча (архивы, отчеты и т.п) — эта часть (унификация сообщений) уже реализована + ряд админских приложений (работа с унификацированными сообщениями), которые будут переделываться в плагины.

Собственно отсюда и вероятность расширения интерфейсов а определить что должен делать гипотетический плагин проблематично.
Re[6]: Расширение функционала плагинов в плагинном приложени
От: nomicon Россия  
Дата: 09.07.09 20:05
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Аноним, Вы писали:


G>>>Если уж нужно расширить интерфейс, то создается наследник с суффиксом 2 в конце, а в коде приложения появляется if, который при необходимости вызывает метод расширенного интерфейса.

А>>С использованием if мы пускаем побоку всю прелесть ООП, и имея скажем 10 новых версий того или иного интерфейса придется делать 10 if? И здравствуй старое доброе структурное программирование?
G>Если будет 10 новых версий это значит что изначально была допущена ошибка в проектировании интерфейсов.
Я описал задачу в посте пониже посмотри. Ну конечно не 10 версий, но 5-7 вполне может возникнуть. Например при возникновении универсального дополнительного функционала в Хост приложении для разгузки функционала плагинов. Хотя, в таком случае, скорее всего это будет абсолютно новый интерфейс. Вобщем есть вероятность многоверсионности.
G>Парочка новых версий для пары интерфейсов — вполне нормальная ситуация, и пара ифов гораздо выгоднее чем пытаться поддерживать труЪ ООП постоянно.
G>А где ты тут увидел структурное программирование?
Структурное, что не перегрузка методов, а использование if, switch для проверки версий интерфейса.
Re[3]: Расширение функционала плагинов в плагинном приложени
От: maloi_alex СССР  
Дата: 09.07.09 22:33
Оценка:
Здравствуйте, nomicon, Вы писали:

N>Здравствуйте, gandjustas, Вы писали:


N>Никто и не говорил про "один плагин — один интерфейс". Я так понимаю идея состоит в том, чтобы плагин говорил главному приложению какие он реализует интерфейсы и главная прога дергала нужные ей, так?.

N> Тогда какова идея реализации новых интерфейсов?
N>1. Создавать новый интерфейс и классом плагина релизовывать старый интерфейс + новый(дополнение к старому). Тогда придется в основном приложении объединять интерфейсы в 1, по-моему так.
N>2. Делать новый интерфейс — наследник старого и делать адаптер с пустыми методами?
N>3. Главная прога работает с кучей интерфейсов — т.е. новый интерфейс — новая куча враждебного для ООП кода
N>со switch и т.п.
N>В MEF как я понял как раз и не предусмотрена версионнось, работа осуществляется в рамках одного домена, а это как я уже сказал ключевая проблема.

N>И большая просьба, если есть у кого ссылки на удачные плагинные движки — киньте сюда если не сложно.


ИМХО, лучше следовать правилам подчиненности. К примеру, зачем хост-приложению подстраиваться под конкретный плагин, если можно предоставить единую точку входа приложения для плагина? И пусть весь функционал будет реализован на стороне главного модуля. К примеру, можно создать строгий набор контрактов (интерфейсов), и пусть плагины ему подчинятся.
Ну и небольшие примеры реализации из известных решений:

Из Delphi:

BorlandIDEServices: IBorlandIDEServices;

IBorlandIDEServices = interface
   ['{C9E8E577-B5D8-43F3-BC84-6A734A015732}']
   function SupportsService(const Service: TGUID): Boolean;
   function GetService(const Service: TGUID): IInterface; overload;
   function GetService(const Service: TGUID; out Svc): Boolean; overload;
end;


Из Expression Blend:


public interface IPackage
{
    // Methods
    void Load(IApplicationService applicationService);
    void Unload();
}

public interface IApplicationService : IServiceProvider
{
    // Methods
    void AddService(Type serviceType, object serviceInstance);
    void RegisterPackage(IPackage package);
    void RemoveService(Type serviceType);
    void UnregisterPackage(IPackage package);

    // Properties
    IAddInService AddInService { get; }
    ICommandBarService CommandBarService { get; }
    ICommandLineService CommandLineService { get; }
    ICommandService CommandService { get; }
    IConfigurationService ConfigurationService { get; }
    bool DiagnosticMode { get; }
    IDocumentService DocumentService { get; }
    IErrorService ErrorService { get; }
    IFeedbackService FeedbackService { get; }
    bool IsReleaseVersion { get; }
    ILicenseService LicenseService { get; }
    string LongApplicationName { get; }
    FrameworkElement MainWindowRootElement { get; set; }
    IMessageDisplayService MessageDisplayService { get; }
    IMessageLoggingService MessageLoggingService { get; }
...
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.