Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 06 2016 22:50:25
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Открытая программная архитектура. Внешние команды (Plug-in компоненты)


USB концентратор

Команда является одним из наиболее популярных шаблонов проектирования. Это абстракция некоторой прикладной операции в контексте вашего приложения. Набор команд может быть закрытым, когда их реализация “зашита” в коде программы, и существует открытый API для их вызова извне другими приложениями или встраиваемыми в приложение внешними программными модулями. Для того чтобы расширить такой набор команд, необходимо внести соответствующие изменения в исходный программный код приложения. Без изменения кода функциональность, доступную через упомянутый выше API не прибавить и не убавить, поэтому в отношении фиксированной версии программного продукта набор команд является закрытым (нерасширяемым).

В этом примере будет рассмотрен вариант подключения открытого набора внешних объектов-команд, выполненных по определенной каркасом приложения программной спецификации. Для добавления новой функциональности достаточно реализовать новый программный компонент по установленной спецификации и расширить библиотеку внешних объектов-команд копированием вновь созданной динамически подключаемой библиотеки (dll) в нужный каталог. Команда может быть подключена к элементам настраиваемого (кастомизируемого) пользовательского интерфейса или являться атомарной операцией (оператором) вашего прикладного интерпретатора. В любом случае, все это определяется требованиями к конкретному программному продукту. Последний подход используется в системах, поддерживающих кастомизацию на базе настройки бизнес-сценариев.

В новом проекте должны быть подключены следующие библиотеки BCL:

using System.IO;
using System.Reflection;

Реализация основана на механизме отражения, а именно на использовании объектов, описывающих типы загружаемой сборки (исполняемой или динамически подключаемой библиотеки, содержащей типы .NET) и используемых для динамического создания их экземпляров, получения их интерфейсов, вызова их методов и манипулирования их свойствами. Нужные типы, интерфейсы, методы и свойства извлекаются из структур данных сборки по своим именам (строковым параметрам), которые, в в свою очередь, могут являться внешними параметрами программы. Суть подхода в следующем: в первую очередь вы определяете правила игры, а именно интерфейс, который должен быть реализован любым внешним, по отношению к вашей программе типом, чтобы его приняли за команду. Далее вы производите поиск таких типов (в приведенном примере поиск достаточно примитивен), на основе результатов поиска формируете коллекцию команд и передаете эту коллекцию в качестве аргумента тому компоненту программы, который в состоянии управлять их запуском и контролировать их исполнение. Механизм отражения используется как раз для того, чтобы выяснить, имеет ли конкретная библиотека в своем составе тип, поддерживающий интерфейс объекта-команды.

public interface IMyApplication {}
public interface IMyCommand
{
    //Подпись команды
    string Caption { get; }
    //Инициализация команды
    bool Initialize(IMyApplication _Context);
    //Деинициализация команды
    bool Uninitialize();
    //Выполнение команды
    bool Execute(string _Parameters);
}

Интерфейс IMyApplication – это контекст вашего приложения, и только посредством него команда может “дергать” за его “рычаги". Естественно, что спецификация этого интерфейса определяется исключительно назначением приложения-контейнера и степенью его “доверия” к поведению внешних команд. И именно интерфейс IMyApplication является реализацией открытой программной архитектуры. Открытой, в нашем случае, для внешних объектов-команд.

Подсистему внешних объектов-команд часто используют для оптимизации выполнения последовательности рутинных операций (бизнес-сценариев). Если вы используете многоцелевое программное средство (ERP, CAD, ГИС), то, с большой вероятностью в ваших действиях можно выделить последовательности одних и тех же команд, которые целесообразно объединить в одну целостную операцию. К примеру, вы осуществляете одну и ту же проводку, выполняете один и тот же вид чертежа, или проводите один и тот же пространственный анализ, и для каждой из этих операций вам необходимо постоянно последовательно выполнять одни и те же действия с программой. Такие операции следует выделять в отдельные подключаемые внешние команды, которые, взаимодействуя с API приложения-контейнера, будут выполнять те самую последовательности автоматически или автоматизировано, и не будут заставлять пользователя делать лишние телодвижения. Это и есть пример кастомизации программного решения.

Интерфейс IMyCommand – это тот самый интерфейс, который должна реализовать каждая потенциальная команда. В самом примитивном варианте он включает методы инициализации и деинициализации контекста, сам метод команды и свойство-подпись для отображения назначения команды в элементах пользовательского интерфейса. Очевидно, что дополнение этой спецификации, например, свойствами Image и CanExecute сделает использование команд более наглядным и адекватным, но здесь я не буду развивать эту тему.

Итак, метод поиска и инициализации внешних команд (думаю, что комментарии излишни):

Dictionary<string, IMyCommand> Load(string _Where)
        {
            Dictionary<string, IMyCommand> _Result;
            _Result = new Dictionary<string, IMyCommand>();

            //Поиск и подключение команд (в текущем каталоге)
            foreach (string _command in Directory.GetFiles(_Where, "*.dll"))
                try
                {
                    Assembly _assm;
                    _assm = Assembly.LoadFrom(_command);

                    foreach (Type _type in _assm.GetTypes())
                        if (_type.GetInterface("IMyCommand") == typeof(IMyCommand))
                            _Result.Add(_type.FullName, (IMyCommand)Activator.CreateInstance(_type));
                }
                catch (Exception ex)
                {
                    //Запись сообщения об ошибке в лог
                    return null;
                }

            return _Result;
        }

Методы инициализации и деинициализации команд, которые следует выполнять в начале и в конце работы приложения:

void Initialize(Dictionary<string, IMyCommand> _Commands)
        {
            foreach (KeyValuePair<string, IMyCommand> _Command in _Commands)
                try
                {
                    _Command.Value.Initialize((IMyApplication)this);
                }
                catch (Exception ex)
                {
                    //Запись сообщения об ошибке в лог
                }
        }

void Uninitialize(Dictionary<string, IMyCommand> _Commands)
        {
            foreach (KeyValuePair<string, IMyCommand> _Command in _Commands)
                try
                {
                    _Command.Value.Uninitialize();
                }
                catch (Exception ex)
                {
                    //Запись сообщения об ошибке в лог
                }
        }

Метод выполнения команды по наименованию ее полного типа:

bool Execute(Dictionary<string, IMyCommand> _Commands, string _Name, string _Parameters)
        {
            if (!_Commands.ContainsKey(_Name))
                throw new InvalidOperationException("Command '" + _Name + "' is not registered!");

            try
            {
                return ((IMyCommand)_Commands[_Name]).Execute(_Parameters);
            }
            catch (Exception ex)
            {
                //Запись сообщения об ошибке в лог
                return false;
            }
        }

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

Пример реализации подключаемых внешних команд (Plug-in компонентов)
Читать далее: встраивание динамически компилируемого кода



Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.