Mercurial > pub > bltoolkit
comparison Source/TypeBuilder/Builders/AbstractClassBuilder.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.Generic; | |
3 using System.Linq; | |
4 using System.Reflection; | |
5 using System.Diagnostics.CodeAnalysis; | |
6 | |
7 namespace BLToolkit.TypeBuilder.Builders | |
8 { | |
9 using Properties; | |
10 using Reflection; | |
11 using Reflection.Emit; | |
12 | |
13 internal class AbstractClassBuilder : ITypeBuilder | |
14 { | |
15 public AbstractClassBuilder(Type sourceType) | |
16 { | |
17 _sourceType = sourceType; | |
18 } | |
19 | |
20 readonly Type _sourceType; | |
21 | |
22 public string AssemblyNameSuffix | |
23 { | |
24 get { return TypeBuilderConsts.AssemblyNameSuffix; } | |
25 } | |
26 | |
27 public Type Build(AssemblyBuilderHelper assemblyBuilder) | |
28 { | |
29 _context = new BuildContext(_sourceType); | |
30 _builders = new AbstractTypeBuilderList(); | |
31 | |
32 _context.TypeBuilders = GetBuilderList(_context.Type); | |
33 _context.AssemblyBuilder = assemblyBuilder; | |
34 | |
35 _builders.AddRange(_context.TypeBuilders); | |
36 _builders.Add(_defaultTypeBuilder); | |
37 | |
38 return Build(); | |
39 } | |
40 | |
41 internal static string GetTypeFullName(Type type) | |
42 { | |
43 var name = type.FullName; | |
44 | |
45 if (type.IsGenericType) | |
46 { | |
47 name = name.Split('`')[0]; | |
48 | |
49 foreach (var t in type.GetGenericArguments()) | |
50 name += "_" + GetTypeFullName(t).Replace('+', '_').Replace('.', '_'); | |
51 } | |
52 | |
53 return name; | |
54 } | |
55 | |
56 internal static string GetTypeShortName(Type type) | |
57 { | |
58 var name = type.Name; | |
59 | |
60 if (type.IsGenericType) | |
61 { | |
62 name = name.Split('`')[0]; | |
63 | |
64 foreach (var t in type.GetGenericArguments()) | |
65 name += "_" + GetTypeFullName(t).Replace('+', '_').Replace('.', '_'); | |
66 } | |
67 | |
68 return name; | |
69 } | |
70 | |
71 public string GetTypeName() | |
72 { | |
73 var typeFullName = _sourceType.FullName; | |
74 var typeShortName = _sourceType.Name; | |
75 | |
76 if (_sourceType.IsGenericType) | |
77 { | |
78 typeFullName = GetTypeFullName (_sourceType); | |
79 typeShortName = GetTypeShortName(_sourceType); | |
80 } | |
81 | |
82 typeFullName = typeFullName. Replace('+', '.'); | |
83 typeShortName = typeShortName.Replace('+', '.'); | |
84 | |
85 typeFullName = typeFullName.Substring(0, typeFullName.Length - typeShortName.Length); | |
86 typeFullName = typeFullName + "BLToolkitExtension." + typeShortName; | |
87 | |
88 return typeFullName; | |
89 } | |
90 | |
91 public Type GetBuildingType() | |
92 { | |
93 return _sourceType; | |
94 } | |
95 | |
96 private static AbstractTypeBuilderList GetBuilderList(TypeHelper type) | |
97 { | |
98 var attrs = type.GetAttributes(typeof(AbstractTypeBuilderAttribute)); | |
99 var builders = new AbstractTypeBuilderList(attrs.Length); | |
100 | |
101 foreach (AbstractTypeBuilderAttribute attr in attrs) | |
102 { | |
103 var builder = attr.TypeBuilder; | |
104 | |
105 if (builder != null) | |
106 { | |
107 builder.TargetElement = type; | |
108 builders.Add(builder); | |
109 } | |
110 } | |
111 | |
112 return builders; | |
113 } | |
114 | |
115 private static readonly DefaultTypeBuilder _defaultTypeBuilder = new DefaultTypeBuilder(); | |
116 | |
117 private BuildContext _context; | |
118 private AbstractTypeBuilderList _builders; | |
119 | |
120 private Type Build() | |
121 { | |
122 DefineNonAbstractType(); | |
123 | |
124 SetID(_builders); | |
125 | |
126 _context.BuildElement = BuildElement.Type; | |
127 | |
128 Build(BuildStep.Before, _builders); | |
129 Build(BuildStep.Build, _builders); | |
130 | |
131 var ids = _builders.ToDictionary(builder => builder, builder => builder.ID); | |
132 | |
133 DefineAbstractProperties(); | |
134 DefineAbstractMethods(); | |
135 OverrideVirtualProperties(); | |
136 OverrideVirtualMethods(); | |
137 DefineInterfaces(); | |
138 | |
139 foreach (var builder in ids.Keys) | |
140 builder.ID = ids[builder]; | |
141 | |
142 _context.BuildElement = BuildElement.Type; | |
143 | |
144 Build(BuildStep.After, _builders); | |
145 | |
146 var initMethod = _context.Type.GetMethod("InitInstance", typeof(InitContext)); | |
147 | |
148 // Finalize constructors. | |
149 // | |
150 if (_context.TypeBuilder.IsDefaultConstructorDefined) | |
151 { | |
152 if (initMethod != null) | |
153 _context.TypeBuilder.DefaultConstructor.Emitter | |
154 .ldarg_0 | |
155 .ldnull | |
156 .callvirt (initMethod) | |
157 ; | |
158 | |
159 _context.TypeBuilder.DefaultConstructor.Emitter.ret(); | |
160 } | |
161 | |
162 if (_context.TypeBuilder.IsInitConstructorDefined) | |
163 { | |
164 if (initMethod != null) | |
165 _context.TypeBuilder.InitConstructor.Emitter | |
166 .ldarg_0 | |
167 .ldarg_1 | |
168 .callvirt (initMethod) | |
169 ; | |
170 | |
171 _context.TypeBuilder.InitConstructor.Emitter.ret(); | |
172 } | |
173 | |
174 if (_context.TypeBuilder.IsTypeInitializerDefined) | |
175 _context.TypeBuilder.TypeInitializer.Emitter.ret(); | |
176 | |
177 // Create the type. | |
178 // | |
179 return _context.TypeBuilder.Create(); | |
180 } | |
181 | |
182 private static int _idCounter; | |
183 | |
184 private static void SetID(AbstractTypeBuilderList builders) | |
185 { | |
186 foreach (var builder in builders) | |
187 builder.ID = ++_idCounter; | |
188 } | |
189 | |
190 private static void CheckCompatibility(BuildContext context, AbstractTypeBuilderList builders) | |
191 { | |
192 for (var i = 0; i < builders.Count; i++) | |
193 { | |
194 var cur = builders[i]; | |
195 | |
196 if (cur == null) | |
197 continue; | |
198 | |
199 for (var j = 0; j < builders.Count; j++) | |
200 { | |
201 var test = builders[j]; | |
202 | |
203 if (i == j || test == null) | |
204 continue; | |
205 | |
206 if (cur.IsCompatible(context, test) == false) | |
207 builders[j] = null; | |
208 } | |
209 } | |
210 | |
211 for (var i = 0; i < builders.Count; i++) | |
212 if (builders[i] == null) | |
213 builders.RemoveAt(i--); | |
214 } | |
215 | |
216 private void DefineNonAbstractType() | |
217 { | |
218 var interfaces = new List<Type>(); | |
219 | |
220 if (_context.Type.IsInterface) | |
221 { | |
222 interfaces.Add(_context.Type); | |
223 _context.InterfaceMap.Add(_context.Type, null); | |
224 } | |
225 | |
226 foreach (var tb in _builders) | |
227 { | |
228 var types = tb.GetInterfaces(); | |
229 | |
230 if (types != null) | |
231 { | |
232 foreach (var t in types) | |
233 { | |
234 if (t == null) | |
235 continue; | |
236 | |
237 if (!t.IsInterface) | |
238 { | |
239 throw new InvalidOperationException( | |
240 string.Format(Resources.AbstractClassBuilder_TypeIsNotAnInterface, t.FullName)); | |
241 } | |
242 | |
243 if (interfaces.Contains(t) == false) | |
244 { | |
245 interfaces.Add(t); | |
246 _context.InterfaceMap.Add(t, tb); | |
247 } | |
248 } | |
249 } | |
250 } | |
251 | |
252 var typeName = GetTypeName(); | |
253 | |
254 _context.TypeBuilder = _context.AssemblyBuilder.DefineType( | |
255 typeName, | |
256 TypeAttributes.Public | TypeAttributes.BeforeFieldInit | (TypeFactory.SealTypes? TypeAttributes.Sealed: 0), | |
257 _context.Type.IsInterface? typeof(object): (Type)_context.Type, | |
258 interfaces.ToArray()); | |
259 | |
260 if (_context.Type.IsSerializable) | |
261 _context.TypeBuilder.SetCustomAttribute(typeof(SerializableAttribute)); | |
262 } | |
263 | |
264 class BuilderComparer : IComparer<IAbstractTypeBuilder> | |
265 { | |
266 public BuilderComparer(BuildContext context) | |
267 { | |
268 _context = context; | |
269 } | |
270 | |
271 readonly BuildContext _context; | |
272 | |
273 [SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")] | |
274 public int Compare(IAbstractTypeBuilder x, IAbstractTypeBuilder y) | |
275 { | |
276 return y.GetPriority(_context) - x.GetPriority(_context); | |
277 } | |
278 } | |
279 | |
280 private void Build(BuildStep step, AbstractTypeBuilderList builders) | |
281 { | |
282 _context.Step = step; | |
283 _context.TypeBuilders.Clear(); | |
284 | |
285 foreach (var builder in builders) | |
286 if (builder.IsApplied(_context, builders)) | |
287 _context.TypeBuilders.Add(builder); | |
288 | |
289 if (_context.IsVirtualMethod || _context.IsVirtualProperty) | |
290 _context.TypeBuilders.Add(_defaultTypeBuilder); | |
291 | |
292 if (_context.TypeBuilders.Count == 0) | |
293 return; | |
294 | |
295 CheckCompatibility(_context, _context.TypeBuilders); | |
296 | |
297 _context.TypeBuilders.Sort(new BuilderComparer(_context)); | |
298 | |
299 for (var i = 0; i < _context.TypeBuilders.Count; i++) | |
300 { | |
301 var builder = _context.TypeBuilders[i]; | |
302 | |
303 builder.Build(_context); | |
304 } | |
305 } | |
306 | |
307 private void BeginEmitMethod(MethodInfo method) | |
308 { | |
309 _context.CurrentMethod = method; | |
310 _context.MethodBuilder = _context.TypeBuilder.DefineMethod(method); | |
311 | |
312 var emit = _context.MethodBuilder.Emitter; | |
313 | |
314 // Label right before return and catch block. | |
315 // | |
316 _context.ReturnLabel = emit.DefineLabel(); | |
317 | |
318 // Create return value. | |
319 // | |
320 if (method.ReturnType != typeof(void)) | |
321 { | |
322 _context.ReturnValue = _context.MethodBuilder.Emitter.DeclareLocal(method.ReturnType); | |
323 emit.Init(_context.ReturnValue); | |
324 } | |
325 | |
326 // Initialize out parameters. | |
327 // | |
328 var parameters = method.GetParameters(); | |
329 | |
330 if (parameters != null) | |
331 emit.InitOutParameters(parameters); | |
332 } | |
333 | |
334 private void EmitMethod( | |
335 AbstractTypeBuilderList builders, MethodInfo methdoInfo, BuildElement buildElement) | |
336 { | |
337 SetID(builders); | |
338 | |
339 _context.BuildElement = buildElement; | |
340 | |
341 var isCatchBlockRequired = false; | |
342 var isFinallyBlockRequired = false; | |
343 | |
344 foreach (var builder in builders) | |
345 { | |
346 isCatchBlockRequired = isCatchBlockRequired || IsApplied(builder, builders, BuildStep.Catch); | |
347 isFinallyBlockRequired = isFinallyBlockRequired || IsApplied(builder, builders, BuildStep.Finally); | |
348 } | |
349 | |
350 BeginEmitMethod(methdoInfo); | |
351 | |
352 Build(BuildStep.Begin, builders); | |
353 | |
354 var emit = _context.MethodBuilder.Emitter; | |
355 var returnLabel = _context.ReturnLabel; | |
356 | |
357 // Begin catch block. | |
358 // | |
359 | |
360 if (isCatchBlockRequired || isFinallyBlockRequired) | |
361 { | |
362 _context.ReturnLabel = emit.DefineLabel(); | |
363 emit.BeginExceptionBlock(); | |
364 } | |
365 | |
366 Build(BuildStep.Before, builders); | |
367 Build(BuildStep.Build, builders); | |
368 Build(BuildStep.After, builders); | |
369 | |
370 if (isCatchBlockRequired || isFinallyBlockRequired) | |
371 { | |
372 emit.MarkLabel(_context.ReturnLabel); | |
373 _context.ReturnLabel = returnLabel; | |
374 } | |
375 | |
376 // End catch block. | |
377 // | |
378 if (isCatchBlockRequired) | |
379 { | |
380 emit | |
381 .BeginCatchBlock(typeof(Exception)); | |
382 | |
383 _context.ReturnLabel = emit.DefineLabel(); | |
384 _context.Exception = emit.DeclareLocal(typeof(Exception)); | |
385 | |
386 emit | |
387 .stloc (_context.Exception); | |
388 | |
389 Build(BuildStep.Catch, builders); | |
390 | |
391 emit | |
392 .rethrow | |
393 .end(); | |
394 | |
395 emit.MarkLabel(_context.ReturnLabel); | |
396 _context.ReturnLabel = returnLabel; | |
397 _context.Exception = null; | |
398 } | |
399 | |
400 if (isFinallyBlockRequired) | |
401 { | |
402 emit.BeginFinallyBlock(); | |
403 _context.ReturnLabel = emit.DefineLabel(); | |
404 | |
405 Build(BuildStep.Finally, builders); | |
406 | |
407 emit.MarkLabel(_context.ReturnLabel); | |
408 _context.ReturnLabel = returnLabel; | |
409 } | |
410 | |
411 if (isCatchBlockRequired || isFinallyBlockRequired) | |
412 emit.EndExceptionBlock(); | |
413 | |
414 Build(BuildStep.End, builders); | |
415 | |
416 EndEmitMethod(); | |
417 } | |
418 | |
419 private void EndEmitMethod() | |
420 { | |
421 var emit = _context.MethodBuilder.Emitter; | |
422 | |
423 // Prepare return. | |
424 // | |
425 emit.MarkLabel(_context.ReturnLabel); | |
426 | |
427 if (_context.ReturnValue != null) | |
428 emit.ldloc(_context.ReturnValue); | |
429 | |
430 emit.ret(); | |
431 | |
432 // Cleanup the context. | |
433 // | |
434 _context.ReturnValue = null; | |
435 _context.CurrentMethod = null; | |
436 _context.MethodBuilder = null; | |
437 } | |
438 | |
439 private static AbstractTypeBuilderList GetBuilders(object[] attributes, object target) | |
440 { | |
441 var builders = new AbstractTypeBuilderList(attributes.Length); | |
442 | |
443 foreach (AbstractTypeBuilderAttribute attr in attributes) | |
444 { | |
445 var builder = attr.TypeBuilder; | |
446 | |
447 builder.TargetElement = target; | |
448 builders.Add(builder); | |
449 } | |
450 | |
451 return builders; | |
452 } | |
453 | |
454 private static AbstractTypeBuilderList GetBuilders(MemberInfo memberInfo) | |
455 { | |
456 return GetBuilders( | |
457 memberInfo.GetCustomAttributes(typeof(AbstractTypeBuilderAttribute), true), memberInfo); | |
458 } | |
459 | |
460 private static AbstractTypeBuilderList GetBuilders(ParameterInfo parameterInfo) | |
461 { | |
462 return GetBuilders( | |
463 parameterInfo.GetCustomAttributes(typeof(AbstractTypeBuilderAttribute), true), parameterInfo); | |
464 } | |
465 | |
466 private static AbstractTypeBuilderList GetBuilders(ParameterInfo[] parameters) | |
467 { | |
468 var builders = new AbstractTypeBuilderList(); | |
469 | |
470 foreach (var pi in parameters) | |
471 { | |
472 var attributes = pi.GetCustomAttributes(typeof(AbstractTypeBuilderAttribute), true); | |
473 | |
474 foreach (AbstractTypeBuilderAttribute attr in attributes) | |
475 { | |
476 var builder = attr.TypeBuilder; | |
477 | |
478 builder.TargetElement = pi; | |
479 builders.Add(builder); | |
480 } | |
481 } | |
482 | |
483 return builders; | |
484 } | |
485 | |
486 private static AbstractTypeBuilderList Combine(params AbstractTypeBuilderList[] builders) | |
487 { | |
488 var list = new AbstractTypeBuilderList(); | |
489 | |
490 foreach (var l in builders) | |
491 list.AddRange(l); | |
492 | |
493 return list; | |
494 } | |
495 | |
496 private bool IsApplied(IAbstractTypeBuilder builder, AbstractTypeBuilderList builders, BuildStep buildStep) | |
497 { | |
498 _context.Step = buildStep; | |
499 return builder.IsApplied(_context, builders); | |
500 } | |
501 | |
502 private bool IsApplied(BuildElement element, AbstractTypeBuilderList builders) | |
503 { | |
504 _context.BuildElement = element; | |
505 | |
506 foreach (var builder in builders) | |
507 { | |
508 if (IsApplied(builder, builders, BuildStep.Before)) return true; | |
509 if (IsApplied(builder, builders, BuildStep.Build)) return true; | |
510 if (IsApplied(builder, builders, BuildStep.After)) return true; | |
511 if (IsApplied(builder, builders, BuildStep.Catch)) return true; | |
512 if (IsApplied(builder, builders, BuildStep.Finally)) return true; | |
513 } | |
514 | |
515 return false; | |
516 } | |
517 | |
518 private static void GetAbstractProperties(Type type, List<PropertyInfo> props) | |
519 { | |
520 if (props.FirstOrDefault(mi => mi.DeclaringType == type) == null) | |
521 { | |
522 props.AddRange( | |
523 type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)); | |
524 | |
525 if (type.IsInterface) | |
526 foreach (var t in type.GetInterfaces()) | |
527 GetAbstractProperties(t, props); | |
528 } | |
529 } | |
530 | |
531 private void DefineAbstractProperties() | |
532 { | |
533 var props = new List<PropertyInfo>(); | |
534 | |
535 GetAbstractProperties(_context.Type, props); | |
536 | |
537 foreach (var pi in props) | |
538 { | |
539 _context.CurrentProperty = pi; | |
540 | |
541 var propertyBuilders = GetBuilders(pi); | |
542 | |
543 var getter = pi.GetGetMethod(true); | |
544 var setter = pi.GetSetMethod(true); | |
545 | |
546 if (getter != null && getter.IsAbstract || | |
547 setter != null && setter.IsAbstract) | |
548 { | |
549 DefineAbstractGetter(pi, getter, propertyBuilders); | |
550 DefineAbstractSetter(pi, setter, propertyBuilders); | |
551 } | |
552 } | |
553 | |
554 _context.CurrentProperty = null; | |
555 } | |
556 | |
557 private void DefineAbstractGetter( | |
558 PropertyInfo propertyInfo, MethodInfo getter, AbstractTypeBuilderList propertyBuilders) | |
559 { | |
560 // Getter can be not defined. We will generate it anyway. | |
561 // | |
562 if (getter == null) | |
563 #if SILVERLIGHT | |
564 return; | |
565 #else | |
566 getter = new FakeGetter(propertyInfo); | |
567 #endif | |
568 | |
569 var builders = Combine( | |
570 GetBuilders(getter.GetParameters()), | |
571 GetBuilders(getter.ReturnParameter), | |
572 GetBuilders(getter), | |
573 propertyBuilders, | |
574 _builders); | |
575 | |
576 EmitMethod(builders, getter, BuildElement.AbstractGetter); | |
577 } | |
578 | |
579 private void DefineAbstractSetter( | |
580 PropertyInfo propertyInfo, | |
581 MethodInfo setter, | |
582 AbstractTypeBuilderList propertyBuilders) | |
583 { | |
584 // Setter can be not defined. We will generate it anyway. | |
585 // | |
586 if (setter == null) | |
587 #if SILVERLIGHT | |
588 return; | |
589 #else | |
590 setter = new FakeSetter(propertyInfo); | |
591 #endif | |
592 | |
593 var builders = Combine( | |
594 GetBuilders(setter.GetParameters()), | |
595 GetBuilders(setter.ReturnParameter), | |
596 GetBuilders(setter), | |
597 propertyBuilders, | |
598 _builders); | |
599 | |
600 EmitMethod(builders, setter, BuildElement.AbstractSetter); | |
601 } | |
602 | |
603 private static void GetAbstractMethods(Type type, List<MethodInfo> methods) | |
604 { | |
605 if (!methods.Exists(mi => mi.DeclaringType == type)) | |
606 { | |
607 methods.AddRange( | |
608 type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)); | |
609 | |
610 if (type.IsInterface) | |
611 foreach (var t in type.GetInterfaces()) | |
612 GetAbstractMethods(t, methods); | |
613 } | |
614 } | |
615 | |
616 private void DefineAbstractMethods() | |
617 { | |
618 var methods = new List<MethodInfo>(); | |
619 | |
620 GetAbstractMethods(_context.Type, methods); | |
621 | |
622 foreach (var method in methods) | |
623 { | |
624 if (method.IsAbstract && (method.Attributes & MethodAttributes.SpecialName) == 0) | |
625 { | |
626 var builders = Combine( | |
627 GetBuilders(method.GetParameters()), | |
628 GetBuilders(method.ReturnParameter), | |
629 GetBuilders(method), | |
630 _builders); | |
631 | |
632 EmitMethod(builders, method, BuildElement.AbstractMethod); | |
633 } | |
634 } | |
635 } | |
636 | |
637 private void OverrideVirtualProperties() | |
638 { | |
639 var props = _context.Type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); | |
640 | |
641 foreach (var pi in props) | |
642 { | |
643 _context.CurrentProperty = pi; | |
644 | |
645 var propertyBuilders = GetBuilders(pi); | |
646 | |
647 var getter = pi.GetGetMethod(true); | |
648 | |
649 if (getter != null && getter.IsVirtual && !getter.IsAbstract && !getter.IsFinal) | |
650 OverrideGetter(getter, propertyBuilders); | |
651 | |
652 var setter = pi.GetSetMethod(true); | |
653 | |
654 if (setter != null && setter.IsVirtual && !setter.IsAbstract && !setter.IsFinal) | |
655 OverrideSetter(setter, propertyBuilders); | |
656 } | |
657 | |
658 _context.CurrentProperty = null; | |
659 } | |
660 | |
661 private void OverrideGetter(MethodInfo getter, AbstractTypeBuilderList propertyBuilders) | |
662 { | |
663 var builders = Combine( | |
664 GetBuilders(getter.GetParameters()), | |
665 GetBuilders(getter.ReturnParameter), | |
666 GetBuilders(getter), | |
667 propertyBuilders, | |
668 _builders); | |
669 | |
670 if (IsApplied(BuildElement.VirtualGetter, builders)) | |
671 EmitMethod(builders, getter, BuildElement.VirtualGetter); | |
672 } | |
673 | |
674 private void OverrideSetter(MethodInfo setter, AbstractTypeBuilderList propertyBuilders) | |
675 { | |
676 var builders = Combine( | |
677 GetBuilders(setter.GetParameters()), | |
678 GetBuilders(setter.ReturnParameter), | |
679 GetBuilders(setter), | |
680 propertyBuilders, | |
681 _builders); | |
682 | |
683 if (IsApplied(BuildElement.VirtualSetter, builders)) | |
684 EmitMethod(builders, setter, BuildElement.VirtualSetter); | |
685 } | |
686 | |
687 private void OverrideVirtualMethods() | |
688 { | |
689 var methods = _context.Type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); | |
690 | |
691 foreach (var method in methods) | |
692 { | |
693 if (method.IsVirtual && | |
694 method.IsAbstract == false && | |
695 method.IsFinal == false && | |
696 (method.Attributes & MethodAttributes.SpecialName) == 0 && | |
697 method.DeclaringType != typeof(object)) | |
698 { | |
699 var builders = Combine( | |
700 GetBuilders(method.GetParameters()), | |
701 GetBuilders(method.ReturnParameter), | |
702 GetBuilders(method), | |
703 _builders); | |
704 | |
705 if (IsApplied(BuildElement.VirtualMethod, builders)) | |
706 EmitMethod(builders, method, BuildElement.VirtualMethod); | |
707 } | |
708 } | |
709 } | |
710 | |
711 private void DefineInterfaces() | |
712 { | |
713 foreach (var de in _context.InterfaceMap) | |
714 { | |
715 _context.CurrentInterface = de.Key; | |
716 | |
717 var interfaceMethods = _context.CurrentInterface.GetMethods(); | |
718 | |
719 foreach (var m in interfaceMethods) | |
720 { | |
721 if (_context.TypeBuilder.OverriddenMethods.ContainsKey(m)) | |
722 continue; | |
723 | |
724 BeginEmitMethod(m); | |
725 | |
726 // Call builder to build the method. | |
727 // | |
728 var builder = de.Value; | |
729 | |
730 if (builder != null) | |
731 { | |
732 builder.ID = ++_idCounter; | |
733 | |
734 _context.BuildElement = BuildElement.InterfaceMethod; | |
735 _context.Step = BuildStep.Build; | |
736 builder.Build(_context); | |
737 } | |
738 | |
739 EndEmitMethod(); | |
740 } | |
741 | |
742 _context.CurrentInterface = null; | |
743 } | |
744 } | |
745 } | |
746 } |