Иногда бывает, что в связи с изменениями необходимо поправить небольшой кусок кода. Но для этого приходится перекомпилировать много сборок, а клиенту ждать следующего релиза. Чтобы ради пары строчек кода не заниматься обновлением всего решения и был написан отдельный модуль, который позволяет компилировать и сохранять исходный код в рантайме.
Полученная сборка компилируется в текущем домене. Благодаря этому, нет проблем с доступом ко всему приложению. При этом, есть вариант напакостить и сломать само приложение, так что пользоваться лучше с осторожностью. Соответственно, при перекомпиляции кода, старая сборка остаётся в контексте запущенного приложения.
В левой панели — список подгруженных сборок. При двойном нажатии на пространство имён (namesapce), оно добавляется в using класса. При нажатии кнопки на тулбаре «Reference», откроется окно добавления новой сборки в проект. (Возможна подгрузка ссылки на сборку из: GAC, Файловой системы, Массива плагинов) Или список ранее добавленных сборок и используемых пространств имён.
Нажатие на кнопку «Full Source», позволяет отобразить весь код класса. По умолчанию, код класса скрыт и для редактирования доступен только динамически вызываемый метод класса. Чтобы вернуть вид редактирования одного метода класса, дополнительный код необходимо будет почитстить вручную.
По кнопке «Inclide Debug Info», можно скомпилировать сборку с .pdb файлом.
Затем идёт выбор языка компиляции и версия фреймворка. Эти параметры я беру из глубин .NET'а, так что необязательно что во всех вариантах будет доступна комиляция или выбор языка. По кнопке «Compile», можо скомпилить и проверить созданный метод и при ошибках компиляции, снизу появится список с сообщениями об ошибках. Пока, при тестировании метода доступны только пустые аргументы вызова.
Для вызова окна редактирования метода, необходимо передать 2 параметра: Идентификатор выхываемого метода и ключ или идентификатор метода, который будет скомпилирован. За сохранность кода отвечает сам плагин компиляции.
//Description of the caller plugin IPluginDescription thisPlugin = this.PluginDescription; //Key for a new method String methodName = "GetSomeCookies"; IWindow window = this.HostWindows.Windows.CreateWindow("425f8b0c-f049-44ee-8375-4cc874d6bf94", "Plugin.Compiler.DocumentCompiler", false, new KeyValuePair<String, Object>("CallerPluginId", thisPlugin.ID), new KeyValuePair<String, Object>("ClassName", methodName));
Для вызова метода, вкупе с идентификаторами плагина и ключом метода, необходимо передать массив параметров. Для примера, представим что наш метод принимает один входящий параметр типа String
.
//Description of the caller plugin IPluginDescription thisPlugin = this.PluginDescription; //Key for a new method String methodName = "GetSomeCookies"; Some input value for the GetSomeCookie(String) method String value = "I want cookie"; IPluginDescription plugin = this.Window.Plugin.Host.Plugins["425f8b0c-f049-44ee-8375-4cc874d6bf94"]; Object result; if(plugin == null) { this.Trace.TraceEvent(TraceEventType.Warning, 5, "Compiler plugin '425f8b0c-f049-44ee-8375-4cc874d6bf94' not installed"); } else { IPluginMethodInfo member = plugin.GetMember("InvokeDynamicMethod"); if(member == null) throw new ArgumentNullException("Method 'InvokeDynamicMethod' not found in plugin '425f8b0c-f049-44ee-8375-4cc874d6bf94'"); result = member.Invoke( thisPlugin, methodName, new Object[] { value, }); }