1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Microsoft Public License. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Microsoft Public License, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Microsoft Public License.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
15 using System; using Microsoft;
18 using System.Collections.Generic;
20 using System.Dynamic.Utils;
22 using Microsoft.Scripting.Utils;
25 using System.Reflection;
26 using System.Reflection.Emit;
27 using System.Security;
29 using System.Threading;
32 namespace System.Linq.Expressions.Compiler {
34 namespace Microsoft.Linq.Expressions.Compiler {
36 internal sealed class AssemblyGen {
37 private static AssemblyGen _assembly;
39 // Testing options. Only ever set in MICROSOFT_SCRIPTING_CORE build
40 // configurations, see SetSaveAssemblies
41 #if MICROSOFT_SCRIPTING_CORE
42 private static string _saveAssembliesPath;
43 private static bool _saveAssemblies;
46 private readonly AssemblyBuilder _myAssembly;
47 private readonly ModuleBuilder _myModule;
49 #if MICROSOFT_SCRIPTING_CORE && !SILVERLIGHT
50 private readonly string _outFileName; // can be null iff !SaveAndReloadAssemblies
51 private readonly string _outDir; // null means the current directory
55 private static AssemblyGen Assembly {
57 if (_assembly == null) {
58 Interlocked.CompareExchange(ref _assembly, new AssemblyGen(), null);
64 private AssemblyGen() {
65 var name = new AssemblyName("Snippets");
67 #if SILVERLIGHT // AssemblyBuilderAccess.RunAndSave, Environment.CurrentDirectory
68 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
69 _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
72 // mark the assembly transparent so that it works in partial trust:
73 var attributes = new[] {
74 new CustomAttributeBuilder(typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes), new object[0])
77 #if MICROSOFT_SCRIPTING_CORE
78 if (_saveAssemblies) {
79 string outDir = _saveAssembliesPath ?? Directory.GetCurrentDirectory();
81 outDir = Path.GetFullPath(outDir);
83 throw Error.InvalidOutputDir();
86 Path.Combine(outDir, name.Name + ".dll");
87 } catch (ArgumentException) {
88 throw Error.InvalidAsmNameOrExtension();
91 _outFileName = name.Name + ".dll";
93 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave, outDir,
94 null, null, null, null, false, attributes);
96 _myModule = _myAssembly.DefineDynamicModule(name.Name, _outFileName, false);
100 _myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run, attributes);
101 _myModule = _myAssembly.DefineDynamicModule(name.Name, false);
104 _myAssembly.DefineVersionInfoResource();
108 private TypeBuilder DefineType(string name, Type parent, TypeAttributes attr) {
109 ContractUtils.RequiresNotNull(name, "name");
110 ContractUtils.RequiresNotNull(parent, "parent");
112 StringBuilder sb = new StringBuilder(name);
114 int index = Interlocked.Increment(ref _index);
118 // There is a bug in Reflection.Emit that leads to
119 // Unhandled Exception: System.Runtime.InteropServices.COMException (0x80131130): Record not found on lookup.
120 // if there is any of the characters []*&+,\ in the type name and a method defined on the type is called.
121 sb.Replace('+', '_').Replace('[', '_').Replace(']', '_').Replace('*', '_').Replace('&', '_').Replace(',', '_').Replace('\\', '_');
123 name = sb.ToString();
125 return _myModule.DefineType(name, attr, parent);
128 internal static TypeBuilder DefineDelegateType(string name) {
129 return Assembly.DefineType(
131 typeof(MulticastDelegate),
132 TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass
136 #if MICROSOFT_SCRIPTING_CORE
137 //Return the location of the saved assembly file.
138 //The file location is used by PE verification in Microsoft.Scripting.
139 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
140 internal string SaveAssembly() {
141 #if !SILVERLIGHT // AssemblyBuilder.Save
142 _myAssembly.Save(_outFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
143 return Path.Combine(_outDir, _outFileName);
149 // NOTE: this method is called through reflection from Microsoft.Scripting
150 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
151 internal static void SetSaveAssemblies(bool enable, string directory) {
152 _saveAssemblies = enable;
153 _saveAssembliesPath = directory;
156 // NOTE: this method is called through reflection from Microsoft.Scripting
157 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
158 internal static string[] SaveAssembliesToDisk() {
159 if (!_saveAssemblies) {
160 return new string[0];
163 var assemlyLocations = new List<string>();
165 // first save all assemblies to disk:
166 if (_assembly != null) {
167 string assemblyLocation = _assembly.SaveAssembly();
168 if (assemblyLocation != null) {
169 assemlyLocations.Add(assemblyLocation);
174 return assemlyLocations.ToArray();
179 internal static class SymbolGuids {
180 internal static readonly Guid DocumentType_Text =
181 new Guid(0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0, 0, 0xf8, 8, 0x49, 0xbd);