0
|
1 using System;
|
|
2 using System.Configuration.Assemblies;
|
|
3 using System.Reflection;
|
|
4 using System.Reflection.Emit;
|
|
5 using System.Security;
|
|
6 using System.Threading;
|
|
7
|
|
8 namespace BLToolkit.Reflection.Emit
|
|
9 {
|
|
10 /// <summary>
|
|
11 /// A wrapper around the <see cref="AssemblyBuilder"/> and <see cref="ModuleBuilder"/> classes.
|
|
12 /// </summary>
|
|
13 /// <include file="Examples.CS.xml" path='examples/emit[@name="Emit"]/*' />
|
|
14 /// <include file="Examples.VB.xml" path='examples/emit[@name="Emit"]/*' />
|
|
15 /// <seealso cref="System.Reflection.Emit.AssemblyBuilder">AssemblyBuilder Class</seealso>
|
|
16 /// <seealso cref="System.Reflection.Emit.ModuleBuilder">ModuleBuilder Class</seealso>
|
|
17 public class AssemblyBuilderHelper
|
|
18 {
|
|
19 /// <summary>
|
|
20 /// Initializes a new instance of the <see cref="AssemblyBuilderHelper"/> class
|
|
21 /// with the specified parameters.
|
|
22 /// </summary>
|
|
23 /// <param name="path">The path where the assembly will be saved.</param>
|
|
24 public AssemblyBuilderHelper(string path) : this(path, null, null)
|
|
25 {
|
|
26 }
|
|
27
|
|
28 /// <summary>
|
|
29 /// Initializes a new instance of the <see cref="AssemblyBuilderHelper"/> class
|
|
30 /// with the specified parameters.
|
|
31 /// </summary>
|
|
32 /// <param name="path">The path where the assembly will be saved.</param>
|
|
33 /// <param name="version">The assembly version.</param>
|
|
34 /// <param name="keyFile">The key pair file to sign the assembly.</param>
|
|
35 public AssemblyBuilderHelper(string path, Version version, string keyFile)
|
|
36 {
|
|
37 if (path == null) throw new ArgumentNullException("path");
|
|
38
|
|
39 var idx = path.IndexOf(',');
|
|
40
|
|
41 if (idx > 0)
|
|
42 {
|
|
43 path = path.Substring(0, idx);
|
|
44
|
|
45 if (path.Length >= 200)
|
|
46 {
|
|
47 idx = path.IndexOf('`');
|
|
48
|
|
49 if (idx > 0)
|
|
50 {
|
|
51 var idx2 = path.LastIndexOf('.');
|
|
52
|
|
53 if (idx2 > 0 && idx2 > idx)
|
|
54 path = path.Substring(0, idx + 1) + path.Substring(idx2 + 1);
|
|
55 }
|
|
56 }
|
|
57 }
|
|
58
|
|
59 path = path.Replace("+", ".").Replace("<", "_").Replace(">", "_");
|
|
60
|
|
61 if (path.Length >= 260)
|
|
62 {
|
|
63 path = path.Substring(0, 248);
|
|
64
|
|
65 for (var i = 0; i < int.MaxValue; i++)
|
|
66 {
|
|
67 var newPath = string.Format("{0}_{1:0000}.dll", path, i);
|
|
68
|
|
69 if (!System.IO.File.Exists(newPath))
|
|
70 {
|
|
71 path = newPath;
|
|
72 break;
|
|
73 }
|
|
74 }
|
|
75 }
|
|
76
|
|
77 var assemblyName = System.IO.Path.GetFileNameWithoutExtension(path);
|
|
78 var assemblyDir = System.IO.Path.GetDirectoryName(path);
|
|
79
|
|
80 Path = path;
|
|
81 _assemblyName.Name = assemblyName;
|
|
82
|
|
83 if (version != null)
|
|
84 _assemblyName.Version = version;
|
|
85
|
|
86 #if !SILVERLIGHT
|
|
87
|
|
88 if (!string.IsNullOrEmpty(keyFile))
|
|
89 {
|
|
90 _assemblyName.Flags |= AssemblyNameFlags.PublicKey;
|
|
91 _assemblyName.KeyPair = new StrongNameKeyPair(System.IO.File.OpenRead(keyFile));
|
|
92 _assemblyName.HashAlgorithm = AssemblyHashAlgorithm.SHA1;
|
|
93 }
|
|
94
|
|
95 #endif
|
|
96
|
|
97 #if DEBUG
|
|
98 _assemblyName.Flags |= AssemblyNameFlags.EnableJITcompileTracking;
|
|
99 #else
|
|
100 _assemblyName.Flags |= AssemblyNameFlags.EnableJITcompileOptimizer;
|
|
101 #endif
|
|
102
|
|
103 _createAssemblyBuilder = _ =>
|
|
104 {
|
|
105 #if SILVERLIGHT
|
|
106 _assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.Run);
|
|
107 #else
|
|
108 _assemblyBuilder =
|
|
109 string.IsNullOrEmpty(assemblyDir)?
|
|
110 Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.RunAndSave):
|
|
111 Thread.GetDomain().DefineDynamicAssembly(_assemblyName, AssemblyBuilderAccess.RunAndSave, assemblyDir);
|
|
112 #endif
|
|
113
|
|
114 _assemblyBuilder.SetCustomAttribute(BLToolkitAttribute);
|
|
115
|
|
116 #if !SILVERLIGHT
|
|
117
|
|
118 _assemblyBuilder.SetCustomAttribute(
|
|
119 new CustomAttributeBuilder(
|
|
120 typeof(AllowPartiallyTrustedCallersAttribute)
|
|
121 .GetConstructor(Type.EmptyTypes),
|
|
122 new object[0]));
|
|
123
|
|
124 #endif
|
|
125 };
|
|
126 }
|
|
127
|
|
128 /// <summary>
|
|
129 /// Gets the path where the assembly will be saved.
|
|
130 /// </summary>
|
|
131 public string Path { get; private set; }
|
|
132
|
|
133 private readonly AssemblyName _assemblyName = new AssemblyName();
|
|
134 /// <summary>
|
|
135 /// Gets AssemblyName.
|
|
136 /// </summary>
|
|
137 public AssemblyName AssemblyName
|
|
138 {
|
|
139 get { return _assemblyName; }
|
|
140 }
|
|
141
|
|
142 readonly Action<int> _createAssemblyBuilder;
|
|
143
|
|
144 AssemblyBuilder _assemblyBuilder;
|
|
145 /// <summary>
|
|
146 /// Gets AssemblyBuilder.
|
|
147 /// </summary>
|
|
148 public AssemblyBuilder AssemblyBuilder
|
|
149 {
|
|
150 get
|
|
151 {
|
|
152 if (_assemblyBuilder == null)
|
|
153 _createAssemblyBuilder(0);
|
|
154 return _assemblyBuilder;
|
|
155 }
|
|
156 }
|
|
157
|
|
158 /// <summary>
|
|
159 /// Gets the path where the assembly will be saved.
|
|
160 /// </summary>
|
|
161 public string ModulePath
|
|
162 {
|
|
163 get { return System.IO.Path.GetFileName(Path); }
|
|
164 }
|
|
165
|
|
166 private ModuleBuilder _moduleBuilder;
|
|
167 /// <summary>
|
|
168 /// Gets ModuleBuilder.
|
|
169 /// </summary>
|
|
170 public ModuleBuilder ModuleBuilder
|
|
171 {
|
|
172 get
|
|
173 {
|
|
174 if (_moduleBuilder == null)
|
|
175 {
|
|
176 _moduleBuilder = AssemblyBuilder.DefineDynamicModule(ModulePath);
|
|
177 _moduleBuilder.SetCustomAttribute(BLToolkitAttribute);
|
|
178
|
|
179 }
|
|
180
|
|
181 return _moduleBuilder;
|
|
182 }
|
|
183 }
|
|
184
|
|
185 private CustomAttributeBuilder _blToolkitAttribute;
|
|
186 /// <summary>
|
|
187 /// Retrieves a cached instance of <see cref="BLToolkit.TypeBuilder.BLToolkitGeneratedAttribute"/> builder.
|
|
188 /// </summary>
|
|
189 public CustomAttributeBuilder BLToolkitAttribute
|
|
190 {
|
|
191 get
|
|
192 {
|
|
193 if (_blToolkitAttribute == null)
|
|
194 {
|
|
195 var at = typeof(TypeBuilder.BLToolkitGeneratedAttribute);
|
|
196 var ci = at.GetConstructor(Type.EmptyTypes);
|
|
197
|
|
198 _blToolkitAttribute = new CustomAttributeBuilder(ci, new object[0]);
|
|
199 }
|
|
200
|
|
201 return _blToolkitAttribute;
|
|
202 }
|
|
203 }
|
|
204
|
|
205 /// <summary>
|
|
206 /// Converts the supplied <see cref="AssemblyBuilderHelper"/> to a <see cref="AssemblyBuilder"/>.
|
|
207 /// </summary>
|
|
208 /// <param name="assemblyBuilder">The <see cref="AssemblyBuilderHelper"/>.</param>
|
|
209 /// <returns>An <see cref="AssemblyBuilder"/>.</returns>
|
|
210 public static implicit operator AssemblyBuilder(AssemblyBuilderHelper assemblyBuilder)
|
|
211 {
|
|
212 if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder");
|
|
213
|
|
214 return assemblyBuilder.AssemblyBuilder;
|
|
215 }
|
|
216
|
|
217 /// <summary>
|
|
218 /// Converts the supplied <see cref="AssemblyBuilderHelper"/> to a <see cref="ModuleBuilder"/>.
|
|
219 /// </summary>
|
|
220 /// <param name="assemblyBuilder">The <see cref="AssemblyBuilderHelper"/>.</param>
|
|
221 /// <returns>A <see cref="ModuleBuilder"/>.</returns>
|
|
222 public static implicit operator ModuleBuilder(AssemblyBuilderHelper assemblyBuilder)
|
|
223 {
|
|
224 if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder");
|
|
225
|
|
226 return assemblyBuilder.ModuleBuilder;
|
|
227 }
|
|
228
|
|
229 /// <summary>
|
|
230 /// Saves this dynamic assembly to disk.
|
|
231 /// </summary>
|
|
232 public void Save()
|
|
233 {
|
|
234 #if !SILVERLIGHT
|
|
235
|
|
236 if (_assemblyBuilder != null)
|
|
237 _assemblyBuilder.Save(ModulePath);
|
|
238
|
|
239 #endif
|
|
240 }
|
|
241
|
|
242 #region DefineType Overrides
|
|
243
|
|
244 /// <summary>
|
|
245 /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name.
|
|
246 /// </summary>
|
|
247 /// <param name="name">The full path of the type.</param>
|
|
248 /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
|
|
249 /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string)">ModuleBuilder.DefineType Method</seealso>
|
|
250 public TypeBuilderHelper DefineType(string name)
|
|
251 {
|
|
252 return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name));
|
|
253 }
|
|
254
|
|
255 /// <summary>
|
|
256 /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name and base type.
|
|
257 /// </summary>
|
|
258 /// <param name="name">The full path of the type.</param>
|
|
259 /// <param name="parent">The Type that the defined type extends.</param>
|
|
260 /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
|
|
261 /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type)">ModuleBuilder.DefineType Method</seealso>
|
|
262 public TypeBuilderHelper DefineType(string name, Type parent)
|
|
263 {
|
|
264 return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name, TypeAttributes.Public, parent));
|
|
265 }
|
|
266
|
|
267 /// <summary>
|
|
268 /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, its attributes, and base type.
|
|
269 /// </summary>
|
|
270 /// <param name="name">The full path of the type.</param>
|
|
271 /// <param name="attrs">The attribute to be associated with the type.</param>
|
|
272 /// <param name="parent">The Type that the defined type extends.</param>
|
|
273 /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
|
|
274 /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type)">ModuleBuilder.DefineType Method</seealso>
|
|
275 public TypeBuilderHelper DefineType(string name, TypeAttributes attrs, Type parent)
|
|
276 {
|
|
277 return new TypeBuilderHelper(this, ModuleBuilder.DefineType(name, attrs, parent));
|
|
278 }
|
|
279
|
|
280 /// <summary>
|
|
281 /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, base type,
|
|
282 /// and the interfaces that the defined type implements.
|
|
283 /// </summary>
|
|
284 /// <param name="name">The full path of the type.</param>
|
|
285 /// <param name="parent">The Type that the defined type extends.</param>
|
|
286 /// <param name="interfaces">The list of interfaces that the type implements.</param>
|
|
287 /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
|
|
288 /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso>
|
|
289 public TypeBuilderHelper DefineType(string name, Type parent, params Type[] interfaces)
|
|
290 {
|
|
291 return new TypeBuilderHelper(
|
|
292 this,
|
|
293 ModuleBuilder.DefineType(name, TypeAttributes.Public, parent, interfaces));
|
|
294 }
|
|
295
|
|
296 /// <summary>
|
|
297 /// Constructs a <see cref="TypeBuilderHelper"/> for a type with the specified name, its attributes, base type,
|
|
298 /// and the interfaces that the defined type implements.
|
|
299 /// </summary>
|
|
300 /// <param name="name">The full path of the type.</param>
|
|
301 /// <param name="attrs">The attribute to be associated with the type.</param>
|
|
302 /// <param name="parent">The Type that the defined type extends.</param>
|
|
303 /// <param name="interfaces">The list of interfaces that the type implements.</param>
|
|
304 /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
|
|
305 /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso>
|
|
306 public TypeBuilderHelper DefineType(string name, TypeAttributes attrs, Type parent, params Type[] interfaces)
|
|
307 {
|
|
308 return new TypeBuilderHelper(
|
|
309 this,
|
|
310 ModuleBuilder.DefineType(name, attrs, parent, interfaces));
|
|
311 }
|
|
312
|
|
313 #endregion
|
|
314 }
|
|
315 }
|