0
|
1 using System;
|
|
2 using System.Collections;
|
|
3 using System.Collections.Generic;
|
|
4 using System.Diagnostics.CodeAnalysis;
|
|
5 using System.Reflection;
|
|
6 using System.Reflection.Emit;
|
|
7 using System.Diagnostics;
|
|
8
|
|
9 using BLToolkit.Reflection;
|
|
10 using BLToolkit.Reflection.Emit;
|
|
11
|
|
12 namespace BLToolkit.TypeBuilder.Builders
|
|
13 {
|
|
14 public abstract class AbstractTypeBuilderBase : IAbstractTypeBuilder
|
|
15 {
|
|
16 public virtual Type[] GetInterfaces()
|
|
17 {
|
|
18 return null;
|
|
19 }
|
|
20
|
|
21 private int _id;
|
|
22 public int ID
|
|
23 {
|
|
24 get { return _id; }
|
|
25 set { _id = value; }
|
|
26 }
|
|
27
|
|
28 private object _targetElement;
|
|
29 public object TargetElement
|
|
30 {
|
|
31 get { return _targetElement; }
|
|
32 set { _targetElement = value; }
|
|
33 }
|
|
34
|
|
35 private BuildContext _context;
|
|
36 public BuildContext Context
|
|
37 {
|
|
38 [DebuggerStepThrough] get { return _context; }
|
|
39 [DebuggerStepThrough] set { _context = value; }
|
|
40 }
|
|
41
|
|
42 public virtual bool IsCompatible(BuildContext context, IAbstractTypeBuilder typeBuilder)
|
|
43 {
|
|
44 return true;
|
|
45 }
|
|
46
|
|
47 protected bool IsRelative(IAbstractTypeBuilder typeBuilder)
|
|
48 {
|
|
49 if (typeBuilder == null) throw new ArgumentNullException("typeBuilder");
|
|
50
|
|
51 return GetType().IsInstanceOfType(typeBuilder) || typeBuilder.GetType().IsInstanceOfType(this);
|
|
52 }
|
|
53
|
|
54 public virtual bool IsApplied(BuildContext context, AbstractTypeBuilderList builders)
|
|
55 {
|
|
56 return false;
|
|
57 }
|
|
58
|
|
59 public virtual int GetPriority(BuildContext context)
|
|
60 {
|
|
61 return TypeBuilderConsts.Priority.Normal;
|
|
62 }
|
|
63
|
|
64 public virtual void Build(BuildContext context)
|
|
65 {
|
|
66 if (context == null) throw new ArgumentNullException("context");
|
|
67
|
|
68 Context = context;
|
|
69
|
|
70 switch (context.Step)
|
|
71 {
|
|
72 case BuildStep.Begin: BeginMethodBuild(); return;
|
|
73 case BuildStep.End: EndMethodBuild(); return;
|
|
74 }
|
|
75
|
|
76 switch (context.BuildElement)
|
|
77 {
|
|
78 case BuildElement.Type:
|
|
79 switch (context.Step)
|
|
80 {
|
|
81 case BuildStep.Before: BeforeBuildType(); break;
|
|
82 case BuildStep.Build: BuildType(); break;
|
|
83 case BuildStep.After: AfterBuildType(); break;
|
|
84 case BuildStep.Catch: CatchBuildType(); break;
|
|
85 case BuildStep.Finally: FinallyBuildType(); break;
|
|
86 }
|
|
87
|
|
88 break;
|
|
89
|
|
90 case BuildElement.AbstractGetter:
|
|
91 switch (context.Step)
|
|
92 {
|
|
93 case BuildStep.Before: BeforeBuildAbstractGetter(); break;
|
|
94 case BuildStep.Build: BuildAbstractGetter(); break;
|
|
95 case BuildStep.After: AfterBuildAbstractGetter(); break;
|
|
96 case BuildStep.Catch: CatchBuildAbstractGetter(); break;
|
|
97 case BuildStep.Finally: FinallyBuildAbstractGetter(); break;
|
|
98 }
|
|
99
|
|
100 break;
|
|
101
|
|
102 case BuildElement.AbstractSetter:
|
|
103 switch (context.Step)
|
|
104 {
|
|
105 case BuildStep.Before: BeforeBuildAbstractSetter(); break;
|
|
106 case BuildStep.Build: BuildAbstractSetter(); break;
|
|
107 case BuildStep.After: AfterBuildAbstractSetter(); break;
|
|
108 case BuildStep.Catch: CatchBuildAbstractSetter(); break;
|
|
109 case BuildStep.Finally: FinallyBuildAbstractSetter(); break;
|
|
110 }
|
|
111
|
|
112 break;
|
|
113
|
|
114 case BuildElement.AbstractMethod:
|
|
115 switch (context.Step)
|
|
116 {
|
|
117 case BuildStep.Before: BeforeBuildAbstractMethod(); break;
|
|
118 case BuildStep.Build: BuildAbstractMethod(); break;
|
|
119 case BuildStep.After: AfterBuildAbstractMethod(); break;
|
|
120 case BuildStep.Catch: CatchBuildAbstractMethod(); break;
|
|
121 case BuildStep.Finally: FinallyBuildAbstractMethod(); break;
|
|
122 }
|
|
123
|
|
124 break;
|
|
125
|
|
126 case BuildElement.VirtualGetter:
|
|
127 switch (context.Step)
|
|
128 {
|
|
129 case BuildStep.Before: BeforeBuildVirtualGetter(); break;
|
|
130 case BuildStep.Build: BuildVirtualGetter(); break;
|
|
131 case BuildStep.After: AfterBuildVirtualGetter(); break;
|
|
132 case BuildStep.Catch: CatchBuildVirtualGetter(); break;
|
|
133 case BuildStep.Finally: FinallyBuildVirtualGetter(); break;
|
|
134 }
|
|
135
|
|
136 break;
|
|
137
|
|
138 case BuildElement.VirtualSetter:
|
|
139 switch (context.Step)
|
|
140 {
|
|
141 case BuildStep.Before: BeforeBuildVirtualSetter(); break;
|
|
142 case BuildStep.Build: BuildVirtualSetter(); break;
|
|
143 case BuildStep.After: AfterBuildVirtualSetter(); break;
|
|
144 case BuildStep.Catch: CatchBuildVirtualSetter(); break;
|
|
145 case BuildStep.Finally: FinallyBuildVirtualSetter(); break;
|
|
146 }
|
|
147
|
|
148 break;
|
|
149
|
|
150 case BuildElement.VirtualMethod:
|
|
151 switch (context.Step)
|
|
152 {
|
|
153 case BuildStep.Before: BeforeBuildVirtualMethod(); break;
|
|
154 case BuildStep.Build: BuildVirtualMethod(); break;
|
|
155 case BuildStep.After: AfterBuildVirtualMethod(); break;
|
|
156 case BuildStep.Catch: CatchBuildVirtualMethod(); break;
|
|
157 case BuildStep.Finally: FinallyBuildVirtualMethod(); break;
|
|
158 }
|
|
159
|
|
160 break;
|
|
161
|
|
162 case BuildElement.InterfaceMethod:
|
|
163 BuildInterfaceMethod();
|
|
164 break;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 protected virtual void BeforeBuildType () {}
|
|
169 protected virtual void BuildType () {}
|
|
170 protected virtual void AfterBuildType () {}
|
|
171 protected virtual void CatchBuildType () {}
|
|
172 protected virtual void FinallyBuildType () {}
|
|
173
|
|
174 protected virtual void BeforeBuildAbstractGetter() {}
|
|
175 protected virtual void BuildAbstractGetter() {}
|
|
176 protected virtual void AfterBuildAbstractGetter() {}
|
|
177 protected virtual void CatchBuildAbstractGetter() {}
|
|
178 protected virtual void FinallyBuildAbstractGetter() {}
|
|
179
|
|
180 protected virtual void BeforeBuildAbstractSetter() {}
|
|
181 protected virtual void BuildAbstractSetter() {}
|
|
182 protected virtual void AfterBuildAbstractSetter() {}
|
|
183 protected virtual void CatchBuildAbstractSetter() {}
|
|
184 protected virtual void FinallyBuildAbstractSetter() {}
|
|
185
|
|
186 protected virtual void BeforeBuildAbstractMethod() {}
|
|
187 protected virtual void BuildAbstractMethod() {}
|
|
188 protected virtual void AfterBuildAbstractMethod() {}
|
|
189 protected virtual void CatchBuildAbstractMethod() {}
|
|
190 protected virtual void FinallyBuildAbstractMethod() {}
|
|
191
|
|
192 protected virtual void BeforeBuildVirtualGetter () {}
|
|
193 protected virtual void BuildVirtualGetter () {}
|
|
194 protected virtual void AfterBuildVirtualGetter () {}
|
|
195 protected virtual void CatchBuildVirtualGetter () {}
|
|
196 protected virtual void FinallyBuildVirtualGetter () {}
|
|
197
|
|
198 protected virtual void BeforeBuildVirtualSetter () {}
|
|
199 protected virtual void BuildVirtualSetter () {}
|
|
200 protected virtual void AfterBuildVirtualSetter () {}
|
|
201 protected virtual void CatchBuildVirtualSetter () {}
|
|
202 protected virtual void FinallyBuildVirtualSetter () {}
|
|
203
|
|
204 protected virtual void BeforeBuildVirtualMethod () {}
|
|
205 protected virtual void BuildVirtualMethod () {}
|
|
206 protected virtual void AfterBuildVirtualMethod () {}
|
|
207 protected virtual void CatchBuildVirtualMethod () {}
|
|
208 protected virtual void FinallyBuildVirtualMethod () {}
|
|
209
|
|
210 protected virtual void BuildInterfaceMethod () {}
|
|
211
|
|
212 protected virtual void BeginMethodBuild () {}
|
|
213 protected virtual void EndMethodBuild () {}
|
|
214
|
|
215 #region Helpers
|
|
216
|
|
217 [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
|
|
218 protected bool CallLazyInstanceInsurer(FieldBuilder field)
|
|
219 {
|
|
220 if (field == null) throw new ArgumentNullException("field");
|
|
221
|
|
222 MethodBuilderHelper ensurer = Context.GetFieldInstanceEnsurer(field.Name);
|
|
223
|
|
224 if (ensurer != null)
|
|
225 {
|
|
226 Context.MethodBuilder.Emitter
|
|
227 .ldarg_0
|
|
228 .call (ensurer);
|
|
229 }
|
|
230
|
|
231 return ensurer != null;
|
|
232 }
|
|
233
|
|
234 [SuppressMessage("Microsoft.Performance", "CA1818:DoNotConcatenateStringsInsideLoops")]
|
|
235 protected virtual string GetFieldName(PropertyInfo propertyInfo)
|
|
236 {
|
|
237 string name = propertyInfo.Name;
|
|
238
|
|
239 if (char.IsUpper(name[0]) && name.Length > 1 && char.IsLower(name[1]))
|
|
240 name = char.ToLower(name[0]) + name.Substring(1, name.Length - 1);
|
|
241
|
|
242 name = "_" + name;
|
|
243
|
|
244 foreach (ParameterInfo p in propertyInfo.GetIndexParameters())
|
|
245 name += "." + p.ParameterType.FullName;//.Replace(".", "_").Replace("+", "_");
|
|
246
|
|
247 return name;
|
|
248 }
|
|
249
|
|
250 protected string GetFieldName()
|
|
251 {
|
|
252 return GetFieldName(Context.CurrentProperty);
|
|
253 }
|
|
254
|
|
255 protected FieldBuilder GetPropertyInfoField(PropertyInfo property)
|
|
256 {
|
|
257 string fieldName = GetFieldName(property) + "_$propertyInfo";
|
|
258 FieldBuilder field = Context.GetField(fieldName);
|
|
259
|
|
260 if (field == null)
|
|
261 {
|
|
262 field = Context.CreatePrivateStaticField(fieldName, typeof(PropertyInfo));
|
|
263
|
|
264 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
265
|
|
266 ParameterInfo[] index = property.GetIndexParameters();
|
|
267
|
|
268 emit
|
|
269 .LoadType (Context.Type)
|
|
270 .ldstr (property.Name)
|
|
271 .LoadType (property.PropertyType)
|
|
272 ;
|
|
273
|
|
274 if (index.Length == 0)
|
|
275 {
|
|
276 emit
|
|
277 .ldsfld (typeof(Type).GetField("EmptyTypes"))
|
|
278 ;
|
|
279 }
|
|
280 else
|
|
281 {
|
|
282 emit
|
|
283 .ldc_i4 (index.Length)
|
|
284 .newarr (typeof(Type))
|
|
285 ;
|
|
286
|
|
287 for (int i = 0; i < index.Length; i++)
|
|
288 emit
|
|
289 .dup
|
|
290 .ldc_i4 (i)
|
|
291 .LoadType (index[i].ParameterType)
|
|
292 .stelem_ref
|
|
293 .end()
|
|
294 ;
|
|
295 }
|
|
296
|
|
297 emit
|
|
298 .call (typeof(TypeHelper).GetMethod("GetPropertyInfo"))
|
|
299 .stsfld (field)
|
|
300 ;
|
|
301 }
|
|
302
|
|
303 return field;
|
|
304 }
|
|
305
|
|
306 protected FieldBuilder GetPropertyInfoField()
|
|
307 {
|
|
308 return GetPropertyInfoField(Context.CurrentProperty);
|
|
309 }
|
|
310
|
|
311 protected FieldBuilder GetParameterField()
|
|
312 {
|
|
313 string fieldName = GetFieldName() + "_$parameters";
|
|
314 FieldBuilder field = Context.GetField(fieldName);
|
|
315
|
|
316 if (field == null)
|
|
317 {
|
|
318 field = Context.CreatePrivateStaticField(fieldName, typeof(object[]));
|
|
319
|
|
320 FieldBuilder piField = GetPropertyInfoField();
|
|
321 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
322
|
|
323 emit
|
|
324 .ldsfld (piField)
|
|
325 .call (typeof(TypeHelper).GetMethod("GetPropertyParameters"))
|
|
326 .stsfld (field)
|
|
327 ;
|
|
328 }
|
|
329
|
|
330 return field;
|
|
331 }
|
|
332
|
|
333 protected FieldBuilder GetTypeAccessorField()
|
|
334 {
|
|
335 string fieldName = "_" + GetObjectType().FullName + "_$typeAccessor";
|
|
336 FieldBuilder field = Context.GetField(fieldName);
|
|
337
|
|
338 if (field == null)
|
|
339 {
|
|
340 field = Context.CreatePrivateStaticField(fieldName, typeof(TypeAccessor));
|
|
341
|
|
342 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
343
|
|
344 emit
|
|
345 .LoadType (GetObjectType())
|
|
346 .call (typeof(TypeAccessor), "GetAccessor", typeof(Type))
|
|
347 .stsfld (field)
|
|
348 ;
|
|
349 }
|
|
350
|
|
351 return field;
|
|
352 }
|
|
353
|
|
354 protected FieldBuilder GetArrayInitializer(Type arrayType)
|
|
355 {
|
|
356 string fieldName = "_array_of_$_" + arrayType.FullName;
|
|
357 FieldBuilder field = Context.GetField(fieldName);
|
|
358
|
|
359 if (field == null)
|
|
360 {
|
|
361 field = Context.CreatePrivateStaticField(fieldName, arrayType);
|
|
362
|
|
363 EmitHelper emit = Context.TypeBuilder.TypeInitializer.Emitter;
|
|
364
|
|
365 int rank = arrayType.GetArrayRank();
|
|
366
|
|
367 if (rank > 1)
|
|
368 {
|
|
369 Type[] parameters = new Type[rank];
|
|
370
|
|
371 for (int i = 0; i < parameters.Length; i++)
|
|
372 {
|
|
373 parameters[i] = typeof(int);
|
|
374 emit.ldc_i4_0.end();
|
|
375 }
|
|
376
|
|
377 ConstructorInfo ci = TypeHelper.GetConstructor(arrayType, parameters);
|
|
378
|
|
379 emit
|
|
380 .newobj (ci)
|
|
381 .stsfld (field)
|
|
382 ;
|
|
383 }
|
|
384 else
|
|
385 {
|
|
386 emit
|
|
387 .ldc_i4_0
|
|
388 .newarr (arrayType.GetElementType())
|
|
389 .stsfld (field)
|
|
390 ;
|
|
391 }
|
|
392 }
|
|
393
|
|
394 return field;
|
|
395 }
|
|
396
|
|
397 protected FieldBuilder GetArrayInitializer()
|
|
398 {
|
|
399 return GetArrayInitializer(Context.CurrentProperty.PropertyType);
|
|
400 }
|
|
401
|
|
402 protected virtual Type GetFieldType()
|
|
403 {
|
|
404 var pi = Context.CurrentProperty;
|
|
405 var index = pi.GetIndexParameters();
|
|
406
|
|
407 switch (index.Length)
|
|
408 {
|
|
409 case 0: return pi.PropertyType;
|
|
410 case 1: return typeof(Dictionary<object,object>);
|
|
411 default:
|
|
412 throw new InvalidOperationException();
|
|
413 }
|
|
414 }
|
|
415
|
|
416 protected virtual Type GetObjectType()
|
|
417 {
|
|
418 return GetFieldType();
|
|
419 }
|
|
420
|
|
421 protected virtual bool IsObjectHolder
|
|
422 {
|
|
423 get { return false; }
|
|
424 }
|
|
425
|
|
426 #endregion
|
|
427 }
|
|
428 }
|