comparison Source/TypeBuilder/Builders/AbstractTypeBuilderBase.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
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 }