[SIZE=2][COLOR=#0000ff][FONT=Courier New]public [/FONT][/COLOR][/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff]interface [/COLOR][/SIZE][SIZE=2][COLOR=#008080]ICustomComponent[/COLOR][/SIZE][SIZE=2] : [/SIZE][SIZE=2][COLOR=#008080]IServiceProvider[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#008080]IDisposable
[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New]{[/FONT]
[/SIZE][FONT=Courier New][SIZE=2][COLOR=#0000ff] public [/COLOR][/SIZE][SIZE=2][COLOR=#008080]String[/COLOR][/SIZE][SIZE=2] ComponentName { [/SIZE][SIZE=2][COLOR=#0000ff]get[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New];}[/FONT]
[FONT=Courier New]}[/FONT]
[/SIZE]
Ищу средства динамического изменения структуры программы
Мне надо сделать дипломный проект. Я хочу чтобы он был полезен.
Решил сделать интрумент, которий позволит на лету изменять структуру програм. Тоесть добавлять/изменять подключенные к ней модули. (Понятно если програма разработана с помощю етого инструмента)
К примеру нужно разработать большой продукт, а внедрение ево в производство будет проходить постепенно. Можно сделать основную часть и продумать интерфейсы обектов которые планируется использовать дальше. Продукт отдается клиету, а потом доделываются модули которые легко подключаются на лету.
Или чтото розрабатывается несколькими людьми. Каждий имеет интерфейс которий он должен подерживать для своего класа. Он делает клас и компилирует в сборку которая потом динамически подключается.
Или уже чтото сделано, а надо поменять функциональность части програмы. Делаем новий модуль, которий ставим вместо старого без перекомпиляции.
Все ето должно бить безопасно с контролем типов интерфейсов итд.
Делать ето хочу на C# с поддержкой CLS
Если ви дочитали до етого места значит моя идея не совсем бредовая :)
Короче я не хочу делать велосипед, но пока ни о чем таком не слишал.
Если кто знает о таком сообщите пожалуйста, дайте линк.
Также интересно мнение нужно ли такое вообще.
ЗИ Извените за мой русский.
RTFM - Reflection
Меня интересует мнение нужно ли такое ? или есть уже такое ?
Я планирую сделать базовый клас которий можно будет подключать к таким же как он. Соответственно все класы должны походить от нево. Дальше будет прога которая позволяет юзеру подключать необходимие ДЛЛ-ки и будет контролировать соответствие типов, а также можно будет сделать какойто файл инициализации в котором будет сохранятся структура созданого приложения.
Всё что нужно для реализации - ты и сам написал :-)
Только вместо базового класса лучше наверно всё таки использовать интерфейс.
Так получится дерево связаных класов.
Ето ведь должна бить универсальная вечь для розработки, например, иннтегрированих САПР.
Еще надобы ловить ексепшены и запоминать какой модуль их визвал.
Еще надо показивать детали тех интерфейсов которие надо реализовать. (Ну длоя того случая если много людей разрабативают большую систему)
1) Reflection Emitting
2) .NET Remoting.
Архитектуру предлагаю такую:
Есть сборка-контроллер модулей. Она содержит в себе необходимые интерфейсы, активаторы и иные инструменты. Создаёшь классы-активаторы для работы с классами подключаемых модулей. Далее с помощью Reflection в указанных модулях выполняется поиск компонент (допустим, компонента должна быть обозначена каким-либо атрибутом и наследовать интерфейс). Далее сборка-контроллер создаёт proxy-типы для всех подключённых модулей. Приложение, используюшее такую сборку контроллер сможет работать со всеми подключёнными модулями прозрачно через proxy-классы.
Ещё советую пользоваться интерфейсом IServiceProvider. Он как раз для этих целей.
Вот только proxy-классы.....
Я хочу сделать так чтоб будущий разработчик компонентов как-можно меньше заботился о подключении.
Тоесть если он пишет класс-компоненту, то она просто должна поддерживать соответственный интерфейс.
А если он хочет чтоб к его компоненте присоединялись другие внешние компоненти из других модулей, то его компонент должен происходить от моего класса которий умеет присоединять к себе другие компоненти.
Я хочу сделать в своем базовом классе список компонентов которие надо присоединить и делать ето в базовом конструкторе.
Таким образом разработчик просто добавляет поинтер на компонент которий надо присоединить в етот список, а дальше роботает с ним как с обичным обьектом.
Может ето глупо ? Если что не так .. посоветуйте.
Но всеже мой главний вопрос: Будет ли ето комуто нужно и полезно ?
Дело в том что модель для PlugIN'ов у каждой программы разные. Всё зависит от специфики самой прграммы. А что касается подключения - тебе в любом случае каким-либо образом придётся указывать файл с компонентами, иначе никак.
ВОТ. Я же и говорю. Хочу сделать универсальное средство.
Пример:
Нужно розработать САПР для ефективного роскроя ткани.
Класс "А" - главний модуль программи. Програма состоит из графического редактора (класс "Б") и компонента который размещает роскройки на куске ткани (класс "С"). Я далею класс "А". Как делать классы "Б" и "С" я пока не знаю. Но я могу предопредилить их интерфейс для взаимодейтвия з классом "А".
Потом ктото берет ети интерфейсы и создает классы "Б" и "С". Потом появляется новый аглоритм ефективного розмещения раскроек. Делаем новий класс "С" и елементарно подключаем его вместо старого.
И так с любой прогой розработаной с поддержкой моево средства.
И без перекомпиляции. А если комуто для реализации графического редактора тоже надо сложних компонентов - он тоже определяет их интерфейс, а создает потом (или кто другой создает).
Нисходящие программирование. Но можно и наоборот.
[QUOTE=3A3-968M] А что касается подключения - тебе в любом случае каким-либо образом придётся указывать файл с компонентами, иначе никак.[/QUOTE]
Да. Иначе юзер каждий раз должен будет искать подходящие классы вручную.
Код:
Далее есть класс CustomActivator наследующий от IServiceProvider. Это класс лучше сделать синглтоном. Вызываем:
Код:
[SIZE=2][COLOR=#008080][FONT=Courier New]CustomActivator[/FONT][/COLOR][/SIZE][FONT=Courier New][SIZE=2] act = [/SIZE][SIZE=2][COLOR=#008080]CustomActivator[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New].CurrentActivator;[/FONT]
[/SIZE][FONT=Courier New][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2] newComponentVersion = ([/SIZE][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2])act.GetService([/SIZE][SIZE=2][COLOR=#0000ff]typeof[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#008080]ICustomComponent[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New]));[/FONT]
[/SIZE][FONT=Courier New][SIZE=2][COLOR=#008080]Activator[/COLOR][/SIZE][SIZE=2].CreateInstance(newComponentVersion, [/SIZE][SIZE=2][COLOR=#800000]"param1"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#800000]"param2"[/COLOR][/SIZE][SIZE=2]);
[/SIZE][/FONT]
[/SIZE][FONT=Courier New][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2] newComponentVersion = ([/SIZE][SIZE=2][COLOR=#008080]Type[/COLOR][/SIZE][SIZE=2])act.GetService([/SIZE][SIZE=2][COLOR=#0000ff]typeof[/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#008080]ICustomComponent[/COLOR][/SIZE][/FONT][SIZE=2][FONT=Courier New]));[/FONT]
[/SIZE][FONT=Courier New][SIZE=2][COLOR=#008080]Activator[/COLOR][/SIZE][SIZE=2].CreateInstance(newComponentVersion, [/SIZE][SIZE=2][COLOR=#800000]"param1"[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#800000]"param2"[/COLOR][/SIZE][SIZE=2]);
[/SIZE][/FONT]
Запрашивает у CustomActivator (это созданный нами класс) класс, который наследует интерфейс ICustomComponent самой последней версии (вот тут средствами Reflection прогоняем подключённый модуль на наличие класса наследующего ICustomComponent). Метод GetService возвращает метаданные класса более новой версии. Далее при помощи активатора из .NET Framework создаём экземпляр класса.