Модульная система в.NET может быть изменена во время выполнения
В настоящее время я работаю над проектом хобби.NET, который включает в себя сложную систему объектов, которые работают в сочетании друг с другом. Однако я столкнулся с небольшой проблемой: я не могу найти в.NET механизм поддержки замены кода во время выполнения и возможности утилизировать старый код, загруженный ранее. Это означает замену модуля / объекта динамически и практически мгновенно, отображая изменения для пользователя, например, когда он перезапускает процедуру, но не всю программу.
Я уже учел возможность AppDomain
для каждой сессии и загрузки необходимых сборок в нее, но это кажется слишком дорогим. Я должен также упомянуть, что каждый сеанс выигрывает от общей базы сборок, например, для подключения к базе данных, так что это означает загрузку этих классов в каждый отдельный сеанс. Выделение данных взад и вперед от отдельных AppDomain
также представляет дополнительные издержки (может использоваться при отправке данных клиентскому приложению через сеть, код для этого содержится в главном AppDomain
, который управляет сессиями).
Есть ли рамки или способ замены / выгрузки отдельных частей кода? Как это делается в реальных приложениях? Может ли быть обходной путь? Или я выбрал неправильный набор инструментов?
5 ответов
Вам нужна какая-то система плагинов с четко определенными интерфейсами. Затем вы загружаете исполняемые файлы (ваш плагин *.dll) и создаете из него объекты, а затем выполняете на нем методы. Когда вы создаете систему, в которой объекты из ваших плагинов должны создаваться через ваш IPluginManager, у вас не возникает проблем с заменой кода во время выполнения.:)
Или же
У вас есть что-то вроде папки с файлами *.cs, которая будет по требованию скомпилирована (в памяти) и создаст из них объекты, которые вы хотите использовать, и вызовите для них методы. Что в основном то же самое, что и выше, без компиляции во время выполнения.
Оттуда вы можете сделать дальнейшие улучшения.
РЕДАКТИРОВАТЬ: Как вы написали, единственная проблема без использования AppDomain заключается в том, что после загрузки не может быть выгружены сборки. Но это не проблема.
Я не думаю, что вам нужны отдельные домены приложений: вы можете динамически загружать сборки в текущем домене приложений. И каждая сборка, вероятно, должна реализовывать определенные интерфейсы (в зависимости от вашего использования). Вы можете использовать класс FileSystemWatcher, например, для загрузки / выгрузки сборок по мере необходимости.
См. http://msdn.microsoft.com/en-us/library/25y1ya39(v=vs.110).aspx
Вы можете взглянуть на MEF. Он расшифровывается как: Managed Extensibility Framework.
Вот еще одна статья об этом MEF на codeproject.
Используется для загрузки dll
это во время выполнения, составляя их. Это то, что обычно используется для plugins
или что-то еще, вы как бы падаете в папку и ожидаете, что она запустится.
Вот ссылка на еще несколько учебных пособий: Где я могу узнать о MEF?
Да, вы правы, просто выгрузить сборку невозможно (только домены приложений). Но я думаю, что одной из особенностей ASP.Net vNext является возможность иметь только сборки в памяти, и когда вы просто изменяете исходный код на диске, он автоматически компилируется и загружается. Для этого должен существовать механизм выгрузки предыдущей версии.
Я думаю, что они делают это, просто создавая домен приложений, в который все сборки загружаются снова, чтобы избежать любого междоменного взаимодействия. Но я действительно не знаю, и, возможно, если бы вы больше изучили механизм их работы в ASP.NET, вы, возможно, найдете хорошее решение. Больше информации о горячих темах от vNext вы также можете найти в блоге Scotts.
Ну, я нашел 2 решения, которые работают для меня, которыми я хотел бы поделиться. Первый заключается в использовании CollectibleAssembly
и определить типы. Это, конечно, немного сложно, и этот тип динамических сборок накладывает ряд ограничений. Другой вариант - использовать язык сценариев, такой как IronPython
или же IronRuby
, Также отличительной особенностью нового компилятора Roslyn является то, что он также предоставляет API-интерфейсы сценариев, ранее недоступные в.NET Framework. Более того, скриптовые языки Roslyn очень похожи на свои полноценные эквиваленты (C# или VB). И я также нашел крошечный пример его способности.