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