annotate Source/TypeBuilder/Builders/ImplementInterfaceBuilder.cs @ 9:1e85f66cf767 default tip

update bltoolkit
author nickolay
date Thu, 05 Apr 2018 20:53:26 +0300
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Reflection.Emit;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 namespace BLToolkit.TypeBuilder.Builders
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 class ImplementInterfaceBuilder : AbstractTypeBuilderBase
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 public ImplementInterfaceBuilder(Type type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 _type = type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 private readonly Type _type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 public override Type[] GetInterfaces()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 return new[] { _type };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 public override bool IsApplied(BuildContext context, AbstractTypeBuilderList builders)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 if (context == null) throw new ArgumentNullException("context");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 return context.BuildElement == BuildElement.InterfaceMethod;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 protected override void BuildInterfaceMethod()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 var returnIfNonZero = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 var returnIfZero = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 if (Context.ReturnValue != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 var attrs = Context.MethodBuilder.OverriddenMethod.ReturnTypeCustomAttributes.GetCustomAttributes(true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 foreach (var o in attrs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 if (o is ReturnIfNonZeroAttribute) returnIfNonZero = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 else if (o is ReturnIfZeroAttribute) returnIfZero = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 var interfaceType = Context.CurrentInterface;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 var emit = Context.MethodBuilder.Emitter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 foreach (var de in Context.Fields)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 var property = de.Key;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 var field = de.Value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 if (field.FieldType.IsPrimitive || field.FieldType == typeof(string))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 var types = field.FieldType.GetInterfaces();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 foreach (var type in types)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 if (type != interfaceType.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 var im = field.FieldType.GetInterfaceMap(type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 for (var j = 0; j < im.InterfaceMethods.Length; j++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 if (im.InterfaceMethods[j] == Context.MethodBuilder.OverriddenMethod)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 var targetMethod = im.TargetMethods[j];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 var label = new Label();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 var checkNull = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 if (CallLazyInstanceInsurer(field) == false && field.FieldType.IsClass)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 // Check if field is null.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 checkNull = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 label = emit.DefineLabel();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 .ldarg_0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 .ldfld (field)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 .brfalse_s (label)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 // this.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 .ldarg_0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 .end();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 // Load the field and prepare it for interface method call if the method is private.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 if (field.FieldType.IsValueType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 if (targetMethod.IsPublic)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 emit.ldflda (field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 .ldfld (field)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 .box (field.FieldType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 if (targetMethod.IsPublic)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 emit.ldfld (field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 .ldfld (field)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 .castclass (interfaceType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 // Check parameter attributes.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 var pi = Context.MethodBuilder.OverriddenMethod.GetParameters();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 for (var k = 0; k < pi.Length; k++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 var attrs = pi[k].GetCustomAttributes(true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 var stop = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 foreach (var a in attrs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 // Parent - set this.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 if (a is ParentAttribute)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 .ldarg_0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 .end()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 if (!TypeHelper.IsSameOrParent(pi[k].ParameterType, Context.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 .castclass (pi[k].ParameterType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 ;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 stop = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 // PropertyInfo.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 if (a is PropertyInfoAttribute)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 var ifb = GetPropertyInfoField(property);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 emit.ldsfld(ifb);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 stop = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 if (stop)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 // Pass argument.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 emit.ldarg ((byte)(k + 1));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 // Call the method.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 if (field.FieldType.IsValueType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 if (targetMethod.IsPublic) emit.call (targetMethod);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 else emit.callvirt (im.InterfaceMethods[j]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 if (targetMethod.IsPublic) emit.callvirt (targetMethod);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 else emit.callvirt (im.InterfaceMethods[j]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 // Return if appropriated result.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 if (Context.ReturnValue != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 emit.stloc(Context.ReturnValue);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 if (returnIfNonZero)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 .ldloc (Context.ReturnValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 .brtrue (Context.ReturnLabel);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 else if (returnIfZero)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 .ldloc (Context.ReturnValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 .brfalse (Context.ReturnLabel);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 if (checkNull)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 emit.MarkLabel(label);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 }