HotReload кода C# другим кодом C# презентация

Содержание

Слайд 2

Development Studio (IDE) Локальный сервер приложений Прикладная разработка DirectumRX Код

Development Studio (IDE)

Локальный сервер приложений

Прикладная разработка DirectumRX

Код платформы (framework)

Прикладной код

Новый прикладной

код

Deploy (dll)

compile

restart

Слайд 3

Development Studio (IDE) Локальный сервер приложений Зачем нам HotReload Код

Development Studio (IDE)

Локальный сервер приложений

Зачем нам HotReload

Код платформы (framework)

Прикладной код

Новый прикладной

код

deploy

Быстрая локальная отладка прикладного кода.
Обычный deploy хорош и надёжен для прода, но медленный из-за перезапуска сервера.

restart

Слайд 4

Дополнительные ограничения и требования Не спасёт, если поменялась структура БД.

Дополнительные ограничения и требования

Не спасёт, если поменялась структура БД.
Надо, чтобы при

Hot Reload могла работать отладка в Dev Studio.
Хорошо бы, чтобы можно использовать не только для серверного кода, но и для клиента (который уже запущен).
Слайд 5

Основная идея Избавиться от перезапуска сервера. Делаем на стороне сервера

Основная идея

Избавиться от перезапуска сервера.
Делаем на стороне сервера точку (контроллер

WebApi, например), которая встроит поданный код в работающее приложение.

Development Studio (IDE)

Локальный сервер приложений

Код платформы

Прикладной код

Новый прикладной код

Исходный код
или сборка

inject

Слайд 6

Решения в лоб Возня с reflection – LoadAssembly (в т.

Решения в лоб

Возня с reflection – LoadAssembly (в т. ч. Shadow

Copy Assemblies).
Managed Extensibility Framework (MEF); в том числе VS-MEF.
Mono.Cecil.
Слайд 7

Решения в лоб. Проблемы Никак не повлияем на уже существующие

Решения в лоб. Проблемы

Никак не повлияем на уже существующие в памяти

объекты,
Новые объекты, создаваемые через new в прикладном коде будут ссылаться на старые типы.
Чтобы это работало нужно:
писать свой загрузчик типов. Если где-то в прикладном коде какая-то прикладная сущность создаётся через new, то придётся модифицировать прикладной код (это плохо);
в случае с MEF по коду надо либо раскидывать специальные атрибуты, либо наследоваться от нужных интерфейсов.
Слайд 8

Компилять на сервере и Emit (v1) CodeDom – компиляция c#

Компилять на сервере и Emit (v1)

CodeDom – компиляция c# в Assembly

сразу в память в AppDomain.
Emit – генерация IL-кода.

Development Studio (IDE)

Локальный сервер приложений

platform

App sources

new app sources

C#

compile

emit

Слайд 9

Компилять на сервере и Emit Проблемы: Emit работает только с

Компилять на сервере и Emit

Проблемы:
Emit работает только с DynamicAssembly (соответстввенно –

DynamicMethod). А в результатет работы CodeDom и компиляции мы получаем, по сути, обычную Assembly.
Чтобы динамический класс отправить в работу, нужно вызвать у него CreateType(). Это блокирует дальнейшие его модификации
Слайд 10

Edit and Continue Встроенный в Visual Studio хитрый механизм, генерирующий

Edit and Continue

Встроенный в Visual Studio хитрый механизм, генерирующий некоторые дельты.
Общедоступного

API нет.
Даже в самой VS механизм не работает в ряде случаев.
Слайд 11

­Method inject v1 MethodInfo methodToReplace = … ; MethodInfo methodToInject

­Method inject v1

MethodInfo methodToReplace = … ; MethodInfo methodToInject = … ;


unsafe { long* inject = (long*)methodToInject.MethodHandle.Value.ToPointer(); long* target = (long*)methodToReplace.MethodHandle.Value.ToPointer();
*tar = *inj; }

Замена указателя на метод:

В реальности чуток сложнее, потому что надо учесть x86/x64, Debug/Release.

Слайд 12

Как хранятся описания классов в .NET Заголовок MethodTable ptr Field

Как хранятся описания классов в .NET

Заголовок
MethodTable ptr
Field value 1
Field value 2

ObjectInstance


ToString()

ptr
Equals() ptr
….
MyMethod1() ptr

MethodTable

{
Console.WriteLine(…);
}

На самом деле тут IL, конечно

Слайд 13

Суть Method Inject v1 Заголовок MethodTable ptr Field value 1

Суть Method Inject v1

Заголовок
MethodTable ptr
Field value 1
Field value 2

Object instance


ToString() ptr
Equals()

ptr
….
MyMethod1() ptr

Method table

{
Console.WriteLine(1);
}

{
Console.WriteLine(2);
}

Слайд 14

­Method inject (v1)

­Method inject (v1)

Слайд 15

Method Inject v1. Что нам надо сделать ещё Сравнить прикладные

Method Inject v1. Что нам надо сделать ещё

Сравнить прикладные исходники и

найти изменившиеся методы.
Передать исходные тексты методов (+ доп. инфа) на сервер
Создать новый класс, засунуть в него методы и скомпилировать в память
(Перед компиляцией надо заменить вcе обращения к this на обращения через Reflection)
Найти старый метод и сделать MethodInject на новый
Слайд 16

…. Code ptr … Method Inject v1. ПРОБЛЕМА! Прекрасно работает,

….
Code ptr

Method Inject v1. ПРОБЛЕМА!

Прекрасно работает, пока мы не вызываем метод. После

первого вызова срабатывает JIT и вся магия пропадает.


….
MyMethod1() ptr

MethodTable

{
Console.WriteLine(1);
}

MethodDesc

Stub

PreJitStub

machine code

Write jmp to machine code

Слайд 17

Method Inject v2 Использование EasyHook Основная идея: Переопределение compileMethod, Сброс состояния Jitted с помощью MethodDesc.Reset()

Method Inject v2

Использование EasyHook
Основная идея:
Переопределение compileMethod,
Сброс состояния Jitted с помощью MethodDesc.Reset()

Слайд 18

Method Inject v2. Проблемки Нормально заработало только на .NET Framework

Method Inject v2. Проблемки

Нормально заработало только на .NET Framework 3.5.
Уж очень

рискованно такое применять в продакшене.
Поддерживать такое от версии к версии .NET – хз, как, потому что влезли конкретно внутрь кухни CLR
Слайд 19

Что за прикладной код Document Name Author Created … ServerHandlers

Что за прикладной код

Document
Name
Author
Created

ServerHandlers
Created()
BeforeSave()
AfterSave()

ServerFunctions
Foo()

ClientHandlers
Showing()

ClientFunctions
Bar()

SharedFunctions
MyFunction1()

Этот класс генерируется платформой

Слайд 20

Class swap Платформенный код создаёт объекы, содержащие прикладной код. Зачем

Class swap

Платформенный код создаёт объекы, содержащие прикладной код.
Зачем менять изворачиваться с

методами, если можно просто подсунуть объект

Document1
Name

IDocument1ServerFunctions
Foo()

Document1ServerFunctions
Foo()

IDocument1ServerFunctions

CreateServerFunctions ()

Слайд 21

Сlass swap. Работающий прототип

Сlass swap. Работающий прототип

Слайд 22

Мораль Исследования – офигенная тема Правильно, что не стали бросаться

Мораль

Исследования – офигенная тема
Правильно, что не стали бросаться делать первое попавшееся.
Нужно

смотреть шире. Упёрлись в подмену кода на низком уровне.
Документирование исследования – вообще тема.
Фича не забыта и может быть когда-нибудь...
Имя файла: HotReload-кода-C#-другим-кодом-C#.pptx
Количество просмотров: 29
Количество скачиваний: 0