Mercurial > pub > bltoolkit
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 } |