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

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

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

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

Открытая программная архитектура. Встраивание динамически компилируемого кода


Plug-in

Из названия многое ясно. Вы реализуете сервис компиляции и исполнения внешнего программного кода в контексте вашего приложения. Благо, с использованием механизма отражения и дополнительных сервисов компиляции программного кода на языке C# этот подход реализуем достаточно легко. Есть одно "но". Возможность просто исполнить любой внешний программный код в контексте своего приложения практически не дает ничего. Какой смысл выполнять операции, не взаимодействующие с окружением приложения-контейнера? Любая кастомизация должна расширять базовую функциональность и настраивать общее поведение программы под требования функционального заказчика. Иными словами, разработчику встраиваемой в ваше приложение компонента-плагина должна быть доступна вся или часть прикладной функциональности контейнера. Передаваться эта функциональность будет так же, как и в случае с внешними объектами-командами – через интерфейс IMyApplication, который играет роль контекста исполнения плагина. Для того, чтобы корректно передавать контекст исполнения внешнему программному коду необходимы гарантии, что этот самый внешний программный код сможет его принять, т.е. предоставит тип с открытым методом, принимающим в качестве параметра ссылку на интерфейс IMyApplication. Для этого на внешний код будет наложено незначительное ограничение: содержать тип, реализующий интерфейс инициализации, определенный приложением-контейнером. В нашем примере таким интерфейсом будет интерфейс IMyMethod.

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

using System.CodeDom.Compiler;
using Microsoft.CSharp;

Далее, мы поступим следующим образом: будем компилировать внешний программный код, искать в полученной динамической сборке тип по предопределенному параметром имени, создавать экземпляр этого типа, получать от него интерфейс IMyMethod и “дергать” за метод Invoke(). Интерфейс IMyMethod, так же, как и интерфейс IMyCommand является частью окружения вашего приложения-контейнера. По-моему, все просто. Код этого алгоритма представлен ниже:

bool Invoke(List<string> _References, string _Code, string _TypeName)
        {
            CompilerParameters _CompilerParameters;
            _CompilerParameters = new CompilerParameters();
            _CompilerParameters.GenerateInMemory = true;

            foreach (string _Reference in _References)
                _CompilerParameters.ReferencedAssemblies.Add(_Reference);

            try
            {
                CompilerResults _CompilerResults;
                _CompilerResults = new CSharpCodeProvider().CompileAssemblyFromSource(_CompilerParameters, _Code);

                if (_CompilerResults.Errors.Count > 0)
                {
                    string _ErrorList;
                    _ErrorList = string.Empty;

                    foreach (CompilerError _Error in _CompilerResults.Errors)
                        _ErrorList = _ErrorList + _Error.ErrorText + Environment.NewLine;

                    throw new ArgumentException(_ErrorList);
                }

                Type _type;
                _type = _CompilerResults.CompiledAssembly.GetType(_TypeName);

                if (_type == null)
                    throw new ArgumentException("Type '" + _TypeName + "' is null!");

                object _object;
                _object = _type.GetConstructor(Type.EmptyTypes).Invoke(null);

                if (_object == null)
                    throw new ArgumentException("Can't create '" + _TypeName + "' instance!");

                return ((IMyMethod)_object).Invoke(this);
            }

            catch (Exception ex)
            {
                //Запись сообщения об ошибке в лог
                return false;
            }
        }

Для того чтобы программный код нормально компилировался, как минимум, в коллекцию ссылок должна быть включена ссылка на библиотеку, содержащую определение интерфейса IMyMethod:

void InvokeSample(string _Code)
        {
            List<string> _References = new List<string>();
            _References.Add("System.dll");
            _References.Add("Библиотека, содержащая определение интерфейса IMyMethod");

            Invoke(_References, _Code, "MyType");
        }

Программный код, передаваемый в качестве параметра в виде строки, должен быть примерно такого вида:

public class MyType : Сборка.Пространство имен.IMyMethod
   {
    bool Сборка.Пространство имен.IMyMethod.Invoke(Сборка.Пространство имен.IMyApplication _Context) 
     {
      //Здесь программный код выполнения команды.
      return true;
     }
   }

Можно не усложнять жизнь пользователям-кастомизаторам и не заставлять их каждый раз в код включать определение класса MyType, а делать это самостоятельно. От них потребуется только реализовать алгоритм работы команды на C#, зная, что им доступен параметр _Context типа IMyApplication. Иными словам, внешний код будет содержать только тело метода Invoke(), а все остальное вы добавите самостоятельно в процессе компиляции. Но, как известно, все упрощения всегда приводят к сужению возможностей: автор плагина, например, не сможет определить свои собственные типы.

На этом, по-моему, стоит закончить текст. То, каким образом “привинтить” внешние команды или динамический код к приложению – вопрос уже "интимного" характера каждого конкретного приложения.

Примеры реализации расширяемой архитектуры приложений на C#
Пример реализации Plug-in компонентов
Пример реализации динамической компиляции

Дополнительные курсы программирования
Курс программирования C# Quick Guide™ (программирование на C#)
Курс программирования для начинающих (основы программирования на C# и VB.NET)



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

Курс для начинающих программистов на 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. Проект Инициативного Народного Фронта Образования - ИНФО-проект.