2. Как это работает: DLR
dynamic тип в C# или “прорывное” направление в .NET
...важно сконцентрировать имеющиеся ресурсы
на основных прорывных направлениях…
В.В. Путин
Игорь Яковлев
iyakovlev@ptsecurity.com
4. Свойства типа dynamic в C#
dynamic объект - принимает значения любого типа
dynamic - ссылочный “тип”
dynamic - объект может учавствовать в любом* выражении C#
тип выражения с dynamic - dynamic*
код для выражений с объектом dynamic создается динамически*
типизация dynamic объектов: динамическая
5. Однако
Вследствие того, что dynamic является не “родным” для C#, можно всегда немного
потроллить компилятор:
new dynamic(); //compile time error
T Foo<T>() where T : new()
{
return new T();
}
…
var variable = Foo<dynamic>(); //будет new object()
6. DLR - dynamic language runtime
DLR
входит в .Net Framework
(начиная с версии 4.0)
предоставляет API для
выполнения программ
одного языка в другом
операции над
объектами с типами
которые неизвестны на
этапе компиляции
7. ¬DLR
не является частью CLR
не подразумевает его
поддержку языком
не вводит в CLR/Framework новых типов
(dynamic - ключевое слово)
DLR
14. LINQ Expression Trees
Деревья выражений представляют код в виде деревьев, где каждая вершина - выражение.
Expression.Add
Expression.Constant(2) Expression.Constant(3)
Выражение 2+3:
24. Перепишем код для a+b на C#:
Фабрика байндера
двоичной операции
Фабрика CallSiteАнонимный класс с полем CallSite - синглтон
Статическая
информация
Результат динамической операции
Делегат динамической операции
26. Что такое CallSite
Кэширует динамические операции (часть реализации Polymorphic Inline Cache)
Содержит операцию необходимую для выполнения динамического вызова
Создает заглушки для динамических вызовов (делегат Update)
Обращается к байндеру динамических вызовов
27. CallSite снаружи
T - Сигнатура операции
Делегат операции
Делегат обновления
Фабрика CallSite
28. Что может Target:
Выполнить проверку своих аргументов на совместимость с операцией
Выполнить динамическую операцию
Сообщить вызвавшему CallSite результат проверки и операции
TARGET
29. Какой тип у Target?!
Target
= Action<T1,T2[,T3…]>
= Func<T1,T2[,T3…],TResult>
T1 - CallSite
T2 - Ресивер
[T3,...] - Аргументы
TResult - Результат
“a+b” - ресивер “a”
“A.b()” - ресивер typeof(A)
“c.Foo()” - ресивер “c”
(MulticastDelegate)
30. .If ($var1 .TypeEqual System.Int32 && $var2 .TypeEqual System.Int32 && $var2 == 2)
{
.Return { (System.Object)($var1 + 2) }
} .Else
{
$callsite.Update()
.Return { .Default(System.Int32) }
}
Какой код внутри Target?
Restriction expression
Ограничение операции
Body expression
Тело операции
Target - это .Net Expressions Tree v2 скомпилированный в лямбду
Пусть Target сгенерирован для операции “a+2”, где a - Int32
32. Правила (Rules)
Restriction expression
Ограничение операции
Body expression
Тело операции
Rule
Правило
Комбинация ограничения и тела называется правилом (Rule)
Динамический делегат - скомпилированное правило
36. Байндеры
Байндер (Binder)
Статическая информация о
динамическом выражении
Набор Bind-методов возвращающих
правило для переданных аргументов
(LINQ Expression Tree v2)
PIC Cache Level 2
FallBack методы
37. Высшая миссия Байндера
Байндер (Binder)
Набор информации для описания
действия которое должно быть
выполнено
Прокладка между резолвером
динамических операций и CallSite
39. 1. Пытается получить готовый делегат через BindDelegate, либо
2. Получает правило в виде Expression Tree через вызов Bind
3. Компилирует правило в делегат и добавляет его в PIC Level 2
abstract CallSiteBinder - базовый байндер
T BindCore<T>(CallSite<T> site, object[] args)
abstract Expression Bind(object[] args, + параметры для Expression Tree)
T virtual BindDelegate<T>(CallSite<T> site, object[] args)
40. abstract DynamicMetaObjectBinder
abstract DynamicMetaObject Bind(DynamicMetaObject reciever, DynamicMetaObject[] args)
1. Сопоставляет аргументы args их “оберткам” типа
DynamicMetaObject (DMO) через DynamicMetaObject.Create(arg)
2. Выделяет первый аргумент (типа DMO) как ресивер
3. Получает DMO с правилом через вызов Bind
4. Строит из DMO выражение .If (Restriction) .Then (.Return Body) ...
sealed override Expression Bind(object[] args, + параметры для E.T.)
41. 12 Разгневанных байндеров
DLR поддерживает 12 типов выражений
Convert
CreateInstance
DeleteIndex
DeleteMember
GetIndex
GetMember
Invoke
InvokeMember
SetIndex
SetMember
UnaryOperation
BinaryOperation
Для каждого выражения есть байндер
унаследованный от DMOBinder
Для краткости функции и байндеры с
__XXX__ в имени заменяются на имена
из этого списка
43. sealed CSharp__XXX__Binder
Вызывает некий RuntimeBinder :)
override sealed DMO Fallback__XXX__(DMO reciever, DMO arg, [DMO arg2...,] DMO errorSuggestion)
И это последний байндер в иерархии
44. И чего?! oO
Остались главные вопросы
Что это за бред?
Что такое DynamicMetaObject (DMO)?
Как из нашего object получается его DMO?
Что такое FallBack?
Кем составляются правила?!
Кому нужен IDynamicMetaObjectProvider?
47. IDynamicMetaObjectProvider
Этот скучный парень просто возвращает DynamicMetaObject
DynamicMetaObject GetMetaObject(Expression parameter)
Если наш объект поддерживает этот интерфейс то
для объекта можно получить DynamicMetaObject!
48. DynamicMetaObject::Bind__XXX__
Все 12 разгневанных байндер-методов DMO вызывают FallBack у байндера который его вызвал ;)
Ну ок, идем обратно
в байдер в метод
Fallback__XXX__ Однако они virtual...хмммм
51. RuntimeBinder
Парень которого нет в MSDN :)
Мы не будем приводить уважаемой публике содержание этого треша
Содержит реализацию семантического Reflection анализатора .Net
Этот парень умеет строить правила для стандартных типов .Net
Но ведь типы...эмм...не всегда стандартные!?
55. Помоги Даше найти смысл жизни...
Выражение с dynamic CallSite.Target(...) CallSite.UpdateAndExecute PIC
CallSiteBinder
Выполнение выражения
DMOBinder__XXX__Binder
reciever.Bind__XXX__(...) CSharp__XXX__Binder.FallBack
аргументы в DMO
64. Что НЕ вошло в доклад
Классы не являющиеся частью прям-ваще реализации (ExpandoObject и DynamicObject)
Как конкретно происходит построение выражений (лучше не надо :))
Как реализовано взаимодействие с COM (вкраце - COM IDispatch)
Что такое и как работает DLR Hosting API (тема на отдельный доклад)
Оказывается там есть еще SymPL (целый функциональный язык в спецификации)
Реализацию многих мелких деталей (Defer, Stitch, генерацию UpdateAndExecute и тп)
65. Куда гуглить
Можно в гугле - есть статьи но мало
C# 5 Unleashed - Bart De Smet (на самом деле средненько)
Pro DLR in .NET 4 - Chaur Wu (поверхностно)
habrahabr - есть пара статей (и вся пара - не очень)
dlr.codeplex.com - developer notes (очень хорошо!)
В исходники и дебаггер - довольно полное раскрытие темы
Можно спросить меня: linkedin.com/in/igoriakovlev
Доклад Карлена Симоняна на .NeXT 2014: bit.do/DLR_lecture
Поиграть с примерами: bit.do/DLR_examples