8.03M
Category: programmingprogramming

Туда и обратно. Тёмная сторона сериализации

1.

Туда и обратно.
Тёмная сторона сериализации
Константин Рудниченко
CTO, Cadwise

2.

2

3.

О себе
● Зарабатываю на жизнь программированием с
2005 года
● Программировал еще на .net framework 1.0
● Помню С# без Generics
○ Складывал объекты ArrayList
● Использовал BinaryFormatter ¯\_(ツ)_/¯
3

4.

“ЗОЧЕМ?
Есть же <выберите свой
сериализатор>?”
4

5.

Варианты
● Protocol Buffers
● Json
○ Newtonsoft.Json
○ System.Text.Json
○ etc
● BinaryFormatter
● XmlFormatter
● другие
5

6.

Причины
6

7.

Причины
● Экзотические форматы
7

8.

Причины
● Экзотические форматы
● Лучшая производительность
8

9.

Причины
● Экзотические форматы
● Лучшая производительность
● Другие сценарии использования Reflection:
○ Data-binding
○ Object-object mapping
○ Логирование: Destructing
9

10.

О докладе
● Доступ к данным: Reflection и альтернативы
● Производительность различных способов доступа
● Участие доступа к данным в процессе
сериализации
10

11.

Прямой доступ vs. Reflection
11

12.

12

13.

System.Reflection
● System.Object
○ GetType()
13

14.

System.Reflection
● System.Object
○ GetType()
● System.Type
○ GetProperties(...)
14

15.

System.Reflection
● System.Object
○ GetType()
● System.Type
○ GetProperties(...)
● System.Reflection.PropertyInfo
○ Name
○ PropertyType
○ GetValue/SetValue
15

16.

“Все знают, что
Reflection это Медленно!!!”
16

17.

Type System Overview
17

18.

Насколько Reflection это медленно?
18

19.

Цифры
19

20.

20

21.

21

22.

22

23.

23

24.

24

25.

25

26.

26

27.

27

28.

Ba Dum Tss!
28

29.

Ba Dum Tss!
29

30.

“Давай закэшируем PropertyInfo!”
30

31.

31

32.

Cached PropertyInfo
32

33.

Cached PropertyInfo
33

34.

34

35.

“Неужели нет другого способа?!”
35

36.

36

37.

FastMember
37

38.

FastMember
38

39.

FastMember
39

40.

40

41.

41

42.

“Безнадёга?”
42

43.

Delegate.CreateDelegate
43

44.

Delegate
Открытые / Закрытые
44

45.

Delegate: открытые/закрытые
45

46.

Delegate: открытые/закрытые
46

47.

Delegate: открытые/закрытые
47

48.

Delegate.CreateDelegate
48

49.

Delegate.CreateDelegate
49

50.

PropertyInfo ➝ MethodInfo
50

51.

PropertyInfo ➝ MethodInfo
GetGetMethod() / GetSetMethod()
51

52.

Delegate.CreateDelegate
52

53.

Delegate.CreateDelegate
53

54.

Delegate.CreateDelegate
54

55.

Delegate.CreateDelegate
55

56.

Delegate.CreateDelegate
56

57.

Delegate.CreateDelegate
57

58.

58

59.

59

60.

“А может генерировать код в runtime?”
60

61.

Генерация кода в runtime
61

62.

Генерация кода в runtime
● IL Emit
62

63.

Генерация кода в runtime
● IL Emit
● Compiled Expression Trees
63

64.

IL Emit
64

65.

Intermediate Language
65

66.

66

67.

public string GetViaProperty() => _test.StringProperty;
67

68.

public string GetViaProperty() => _test.StringProperty;
.method private hidebysig
static string GetViaProperty( class Test target)
cil managed
{
.maxstack 1
ldarg.0
callvirt instance string Test::get_StringProperty()
ret
}
68

69.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod(true);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
69

70.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod(true);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
70

71.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod(true);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
71

72.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod(true);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
72

73.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod(true);
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
73

74.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
74

75.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
75

76.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
76

77.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
77

78.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
78

79.

public static Func<TTarget, TParam> GenerateGetter<TTarget, TParam>(PropertyInfo property)
{
var method = new DynamicMethod(property.Name + "GetterTyped", typeof(TParam),
new[] { typeof(TTarget) },
Module, true);
var gen = method.GetILGenerator();
var getMethod = property.GetGetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Call, getMethod);
gen.Emit(OpCodes.Ret);
return (Func<TTarget, TParam>)method.CreateDelegate(typeof(Func<TTarget, TParam>));
}
79

80.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
80

81.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
81

82.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
82

83.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
83

84.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
84

85.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
85

86.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
86

87.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
87

88.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
88

89.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
89

90.

static Action<TTarget, TParam> GenerateSetter<TTarget, TParam>(PropertyInfo propertyInfo)
{
var method = new DynamicMethod(propertyInfo.Name + "SetterTyped", null,
new[] { typeof(TTarget), typeof(TParam) }, Module, true);
var gen = method.GetILGenerator();
var setMethod = propertyInfo.GetSetMethod();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Call, setMethod);
gen.Emit(OpCodes.Ret);
return (Action<TTarget, TParam>)method.CreateDelegate(typeof(Action<TTarget, TParam>));
}
90

91.

Intermediate Language
91

92.

Intermediate Language
92

93.

Intermediate Language
93

94.

Compiled Expression Trees
94

95.

Expression Trees
95

96.

Expression Trees
● Lambda Expressions
96

97.

Expression Trees
● Lambda Expressions
● API
97

98.

Expression Trees: Lambda
98

99.

Expression Trees: Lambda
99

100.

Expression Trees: API
100

101.

101

102.

102

103.

103

104.

104

105.

105

106.

106

107.

107

108.

108

109.

109

110.

110

111.

111

112.

112

113.

113

114.

114

115.

Expression Trees: API
115

116.

Expression Trees: API
116

117.

Expression Trees: API
117

118.

Expression Trees: API
118

119.

119

120.

120

121.

Ни рефлексией единой
● Reflection - медленно
121

122.

Ни рефлексией единой
● Reflection - медленно
● Альтернативы “из коробки” - быстрее
122

123.

Ни рефлексией единой
● Reflection - медленно
● Альтернативы “из коробки” - быстрее
○ Требуют усилий
123

124.

“Погоди! Но ...”
124

125.

“Делегаты специфицированы
конкретными типами целевого
объекта и его свойства!”
125

126.

126

127.

127

128.

128

129.

PropertyInfo.GetValue
129

130.

Delegate.CreateDelegate
130

131.

Delegate.CreateDelegate
131

132.

System.ArgumentException
Cannot bind to the target method because its signature is not compatible
with that of the delegate type.
at System.Delegate.CreateDelegate(Type type, MethodInfo method,
Boolean throwOnBindFailure)
at System.Delegate.CreateDelegate(Type type, MethodInfo method)
at Program.Main() in Program.cs
132

133.

“Эх! А счастье было так близко...”
133

134.

Delegate (object, object)
134

135.

Delegate (object, object)
135

136.

Delegate (object, object)
136

137.

Delegate (object, object)
137

138.

Delegate (object, object)
138

139.

Delegate (object, object)
139

140.

Delegate (object, object)
140

141.

Delegate (object, object)
141

142.

Delegate (object, object)
142

143.

143

144.

Delegate (object, object)
144

145.

Delegate (object, object)
145

146.

ILGen (object, object)
146

147.

ILGen (object, object)
147

148.

ILGen (object, object)
148

149.

ILGen (object, object)
149

150.

ILGen (object, object)
150

151.

ILGen (object, object)
151

152.

Expression Trees (object, object)
152

153.

Expression Trees (object, object)
153

154.

Expression Trees (object, object)
154

155.

Expression Trees (object, object)
155

156.

Expression Trees (object, object)
156

157.

157

158.

158

159.

Ни рефлексией единой
● Reflection - медленно
159

160.

Ни рефлексией единой
● Reflection - медленно
○ Нетипизированный доступ
160

161.

Ни рефлексией единой
● Reflection - медленно
○ Нетипизированный доступ
● Альтернативы “из коробки” - быстрее
161

162.

Ни рефлексией единой
● Reflection - медленно
○ Нетипизированный доступ
● Альтернативы “из коробки” - быстрее
○ Типизированный доступ
162

163.

Ни рефлексией единой
● Reflection - медленно
○ Нетипизированный доступ
● Альтернативы “из коробки” - быстрее
○ Типизированный доступ
○ Reflection-like
163

164.

Ни рефлексией единой
● Reflection - медленно
○ Нетипизированный доступ
● Альтернативы “из коробки” - быстрее
○ Типизированный доступ
○ Reflection-like
○ Требуют усилий
164

165.

“А что если ValueType? Boxing же!”
165

166.

ValueType
166

167.

ValueType
167

168.

ValueType
168

169.

169

170.

170

171.

171

172.

Ни рефлексией единой: Value Type
172

173.

Ни рефлексией единой: Value Type
● Reflection: boxing
173

174.

Ни рефлексией единой: Value Type
● Reflection: boxing
● Альтернатива
○ Reflection-like: boxing
174

175.

Ни рефлексией единой: Value Type
● Reflection: boxing
● Альтернатива
○ Reflection-like: boxing
○ Типизированный доступ: no boxing
175

176.

Приватные данные
176

177.

177

178.

178

179.

179

180.

180

181.

Доступ к данным
181

182.

Доступ к данным
● Reflection
182

183.

Доступ к данным
● Reflection:
○ Медленно
183

184.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
184

185.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы
185

186.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы:
○ Сильно быстрее Reflection
186

187.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы:
○ Сильно быстрее Reflection
○ Boxing
187

188.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы:
○ Сильно быстрее Reflection
○ Boxing / No Boxing
188

189.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы:
○ Сильно быстрее Reflection
○ Boxing / No Boxing
● Можно и приватные данные (поля, свойства)
189

190.

Доступ к данным
● Reflection:
○ Медленно
○ Boxing
● Альтернативы:
○ Сильно быстрее Reflection
○ Boxing / No Boxing
● Можно и приватные данные (поля, свойства)
● Прямое чтение/запись не обойти
190

191.

191

192.

Сценарий использования
192

193.

Сериализация
193

194.

Сериализация
194

195.

Сериализация
195

196.

Сериализация
196

197.

Сериализация
197

198.

Сериализация
198

199.

Но!
199

200.

Сгенерированный сериализатор
200

201.

Сгенерированный сериализатор
201

202.

Сериализация
202

203.

203

204.

204

205.

205

206.

206

207.

ValueType. Reflection-like
207

208.

ValueType. Generated
208

209.

209

210.

Serializer
Size in bytes
Google.Protobuf
17
Custom(Property)
18
Custom(Expression Trees)
18
BinaryFormatter
236
210

211.

211

212.

212

213.

213

214.

214

215.

Ни рефлексией единой
BinaryFormatter
Newtonsoft.Json
System.Text.Json
Google.Protobuf
AutoMapper
215

216.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json
System.Text.Json
Google.Protobuf
AutoMapper
216

217.

Ни рефлексией единой
BinaryFormatter: Reflection ¯\_(ツ)_/¯
Newtonsoft.Json
System.Text.Json
Google.Protobuf
AutoMapper
217

218.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json: IL Emit
System.Text.Json
Google.Protobuf
AutoMapper
218

219.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json: IL Emit
System.Text.Json: IL Emit
Google.Protobuf
AutoMapper
219

220.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json: IL Emit
System.Text.Json: IL Emit
Google.Protobuf: Property
AutoMapper
220

221.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json: IL Emit
System.Text.Json: IL Emit
Google.Protobuf: Property (Генерация C# - кода)
AutoMapper
221

222.

Ни рефлексией единой
BinaryFormatter: Reflection
Newtonsoft.Json: IL Emit
System.Text.Json: IL Emit
Google.Protobuf: Property (Генерация C# - кода)
AutoMapper: Expression Trees
222

223.

Осталось за скобками
Безопасность
Инстанцирование объектов (new, CreateInstance)
Парсинг данных
Схема и версионирование данных
Генерация C# - кода
223

224.

Ни рефлексией единой
● Reflection - медленно
● Есть достойные альтернативы:
○ CreateDelegate / IL Emit / Expression Trees
● Доступ к данным еще не всё
● Runtime генерация кода для “сложных” случаев
224

225.

225

226.

Константин Рудниченко
технический директор Cadwise
[email protected]
https://t.me/krudnichenko
https://twitter.com/KRudnichenko
http://cadwise.ru
226
English     Русский Rules