annotate Source/Reflection/Emit/MethodBuilderHelper.cs @ 4:f757da6161a1

!bug 100 + 2h fixed gregression
author cin
date Sun, 24 Aug 2014 17:57:42 +0400
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.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Reflection.Emit;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 namespace BLToolkit.Reflection.Emit
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 /// A wrapper around the <see cref="MethodBuilder"/> class.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 /// <include file="Examples.CS.xml" path='examples/emit[@name="Emit"]/*' />
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 /// <include file="Examples.VB.xml" path='examples/emit[@name="Emit"]/*' />
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 /// <seealso cref="System.Reflection.Emit.MethodBuilder">MethodBuilder Class</seealso>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 public class MethodBuilderHelper : MethodBuilderBase
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 /// Initializes a new instance of the <see cref="MethodBuilderHelper"/> class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 /// with the specified parameters.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 /// <param name="typeBuilder">Associated <see cref="TypeBuilderHelper"/>.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 /// <param name="methodBuilder">A <see cref="MethodBuilder"/></param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 public MethodBuilderHelper(TypeBuilderHelper typeBuilder, MethodBuilder methodBuilder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 : base(typeBuilder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 if (methodBuilder == null) throw new ArgumentNullException("methodBuilder");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28 _methodBuilder = methodBuilder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 methodBuilder.SetCustomAttribute(Type.Assembly.BLToolkitAttribute);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 /// Sets a custom attribute using a custom attribute type.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 /// <param name="attributeType">Attribute type.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 public void SetCustomAttribute(Type attributeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 if (attributeType == null) throw new ArgumentNullException("attributeType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 ConstructorInfo ci = attributeType.GetConstructor(System.Type.EmptyTypes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(ci, new object[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 _methodBuilder.SetCustomAttribute(caBuilder);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 /// Sets a custom attribute using a custom attribute type
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 /// and named properties.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 /// <param name="attributeType">Attribute type.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 /// <param name="properties">Named properties of the custom attribute.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 /// <param name="propertyValues">Values for the named properties of the custom attribute.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 public void SetCustomAttribute(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 Type attributeType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 PropertyInfo[] properties,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 object[] propertyValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 if (attributeType == null) throw new ArgumentNullException("attributeType");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 ConstructorInfo ci = attributeType.GetConstructor(System.Type.EmptyTypes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 ci, new object[0], properties, propertyValues);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 _methodBuilder.SetCustomAttribute(caBuilder);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 /// Sets a custom attribute using a custom attribute type
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 /// and named property.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 /// <param name="attributeType">Attribute type.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 /// <param name="propertyName">A named property of the custom attribute.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 /// <param name="propertyValue">Value for the named property of the custom attribute.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 public void SetCustomAttribute(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 Type attributeType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 string propertyName,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 object propertyValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 SetCustomAttribute(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 attributeType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 new PropertyInfo[] { attributeType.GetProperty(propertyName) },
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 new object[] { propertyValue });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 /// Initializes a new instance of the <see cref="MethodBuilderHelper"/> class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 /// with the specified parameters.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 /// <param name="typeBuilder">Associated <see cref="TypeBuilderHelper"/>.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 /// <param name="methodBuilder">A <see cref="MethodBuilder"/></param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 /// <param name="genericArguments">Generic arguments of the method.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 /// <param name="returnType">The return type of the method.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 /// <param name="parameterTypes">The types of the parameters of the method.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 internal MethodBuilderHelper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 TypeBuilderHelper typeBuilder,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 MethodBuilder methodBuilder,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 Type[] genericArguments,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 Type returnType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 Type[] parameterTypes
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 )
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 : base(typeBuilder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 if (methodBuilder == null) throw new ArgumentNullException("methodBuilder");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 if (genericArguments == null) throw new ArgumentNullException("genericArguments");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 _methodBuilder = methodBuilder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 var genArgNames = genericArguments.Select(t => t.Name).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110 var genParams = methodBuilder.DefineGenericParameters(genArgNames);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 // Copy parameter constraints.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 List<Type> interfaceConstraints = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 for (var i = 0; i < genParams.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 genParams[i].SetGenericParameterAttributes(genericArguments[i].GenericParameterAttributes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 foreach (var constraint in genericArguments[i].GetGenericParameterConstraints())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 if (constraint.IsClass)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 genParams[i].SetBaseTypeConstraint(constraint);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 if (interfaceConstraints == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 interfaceConstraints = new List<Type>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 interfaceConstraints.Add(constraint);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 if (interfaceConstraints != null && interfaceConstraints.Count != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 genParams[i].SetInterfaceConstraints(interfaceConstraints.ToArray());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 interfaceConstraints.Clear();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 // When a method contains a generic parameter we need to replace all
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 // generic types from methodInfoDeclaration with local ones.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 for (var i = 0; i < parameterTypes.Length; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 parameterTypes[i] = TypeHelper.TranslateGenericParameters(parameterTypes[i], genParams);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 methodBuilder.SetParameters(parameterTypes);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 methodBuilder.SetReturnType(TypeHelper.TranslateGenericParameters(returnType, genParams));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 // Once all generic stuff is done is it is safe to call SetCustomAttribute
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 methodBuilder.SetCustomAttribute(Type.Assembly.BLToolkitAttribute);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 private readonly MethodBuilder _methodBuilder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 /// Gets MethodBuilder.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 public MethodBuilder MethodBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 get { return _methodBuilder; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 /// Converts the supplied <see cref="MethodBuilderHelper"/> to a <see cref="MethodBuilder"/>.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 /// <param name="methodBuilder">The <see cref="MethodBuilderHelper"/>.</param>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 /// <returns>A <see cref="MethodBuilder"/>.</returns>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 public static implicit operator MethodBuilder(MethodBuilderHelper methodBuilder)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 if (methodBuilder == null) throw new ArgumentNullException("methodBuilder");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 return methodBuilder.MethodBuilder;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 private EmitHelper _emitter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 /// Gets <see cref="EmitHelper"/>.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 public override EmitHelper Emitter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 get
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 if (_emitter == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 _emitter = new EmitHelper(this, _methodBuilder.GetILGenerator());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 return _emitter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 private MethodInfo _overriddenMethod;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 /// Gets or sets the base type method overridden by this method, if any.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 public MethodInfo OverriddenMethod
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 get { return _overriddenMethod; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 set { _overriddenMethod = value; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 /// <summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 /// Returns the type that declares this method.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 /// </summary>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 public Type DeclaringType
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 get { return _methodBuilder.DeclaringType; }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 }