2 // reflection.cs: System.Reflection and System.Reflection.Emit specific implementations
4 // Author: Marek Safar (marek.safar@gmail.com)
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 // Copyright 2009-2010 Novell, Inc.
13 using System.Collections.Generic;
14 using System.Reflection;
16 using System.Runtime.CompilerServices;
17 using System.Reflection.Emit;
18 using System.Security;
23 public class ReflectionImporter
25 public ReflectionImporter (ModuleContainer module, BuildinTypes buildin)
27 throw new NotSupportedException ();
30 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
32 throw new NotSupportedException ();
35 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
37 throw new NotSupportedException ();
40 public TypeSpec ImportType (Type type)
42 throw new NotSupportedException ();
46 public sealed class ReflectionImporter : MetadataImporter
48 public ReflectionImporter (ModuleContainer module, BuildinTypes buildin)
54 public override void AddCompiledType (TypeBuilder builder, TypeSpec spec)
58 protected override MemberKind DetermineKindFromBaseType (Type baseType)
60 if (baseType == typeof (ValueType))
61 return MemberKind.Struct;
63 if (baseType == typeof (System.Enum))
64 return MemberKind.Enum;
66 if (baseType == typeof (MulticastDelegate))
67 return MemberKind.Delegate;
69 return MemberKind.Class;
72 public override void GetCustomAttributeTypeName (CustomAttributeData cad, out string typeNamespace, out string typeName)
74 var dt = cad.Constructor.DeclaringType;
75 typeNamespace = dt.Namespace;
79 protected override bool HasVolatileModifier (Type[] modifiers)
81 foreach (var t in modifiers) {
82 if (t == typeof (IsVolatile))
89 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
91 // It can be used more than once when importing same assembly
92 // into 2 or more global aliases
93 var definition = GetAssemblyDefinition (assembly);
96 // This part tries to simulate loading of top-level
97 // types only, any missing dependencies are ignores here.
98 // Full error report is reported later when the type is
103 all_types = assembly.GetTypes ();
104 } catch (ReflectionTypeLoadException e) {
108 ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
111 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
113 var module_definition = new ImportedModuleDefinition (module, this);
114 module_definition.ReadAttributes ();
118 all_types = module.GetTypes ();
119 } catch (ReflectionTypeLoadException e) {
123 ImportTypes (all_types, targetNamespace, false);
125 return module_definition;
128 void Initialize (BuildinTypes buildin)
131 // Setup mapping for build-in types to avoid duplication of their definition
133 compiled_types.Add (typeof (object), buildin.Object);
134 compiled_types.Add (typeof (System.ValueType), buildin.ValueType);
135 compiled_types.Add (typeof (System.Attribute), buildin.Attribute);
137 compiled_types.Add (typeof (int), buildin.Int);
138 compiled_types.Add (typeof (long), buildin.Long);
139 compiled_types.Add (typeof (uint), buildin.UInt);
140 compiled_types.Add (typeof (ulong), buildin.ULong);
141 compiled_types.Add (typeof (byte), buildin.Byte);
142 compiled_types.Add (typeof (sbyte), buildin.SByte);
143 compiled_types.Add (typeof (short), buildin.Short);
144 compiled_types.Add (typeof (ushort), buildin.UShort);
146 compiled_types.Add (typeof (System.Collections.IEnumerator), buildin.IEnumerator);
147 compiled_types.Add (typeof (System.Collections.IEnumerable), buildin.IEnumerable);
148 compiled_types.Add (typeof (System.IDisposable), buildin.IDisposable);
150 compiled_types.Add (typeof (char), buildin.Char);
151 compiled_types.Add (typeof (string), buildin.String);
152 compiled_types.Add (typeof (float), buildin.Float);
153 compiled_types.Add (typeof (double), buildin.Double);
154 compiled_types.Add (typeof (decimal), buildin.Decimal);
155 compiled_types.Add (typeof (bool), buildin.Bool);
156 compiled_types.Add (typeof (System.IntPtr), buildin.IntPtr);
157 compiled_types.Add (typeof (System.UIntPtr), buildin.UIntPtr);
159 compiled_types.Add (typeof (System.MulticastDelegate), buildin.MulticastDelegate);
160 compiled_types.Add (typeof (System.Delegate), buildin.Delegate);
161 compiled_types.Add (typeof (System.Enum), buildin.Enum);
162 compiled_types.Add (typeof (System.Array), buildin.Array);
163 compiled_types.Add (typeof (void), buildin.Void);
164 compiled_types.Add (typeof (System.Type), buildin.Type);
165 compiled_types.Add (typeof (System.Exception), buildin.Exception);
166 compiled_types.Add (typeof (System.RuntimeFieldHandle), buildin.RuntimeFieldHandle);
167 compiled_types.Add (typeof (System.RuntimeTypeHandle), buildin.RuntimeTypeHandle);
171 [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)]
172 struct SingleConverter
174 [System.Runtime.InteropServices.FieldOffset (0)]
176 [System.Runtime.InteropServices.FieldOffset (0)]
179 public static int SingleToInt32Bits (float v)
181 SingleConverter c = new SingleConverter ();
189 public class AssemblyDefinitionDynamic : AssemblyDefinition
192 // In-memory only assembly container
194 public AssemblyDefinitionDynamic (ModuleContainer module, string name)
195 : base (module, name)
200 // Assembly container with file output
202 public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName)
203 : base (module, name, fileName)
207 public Module IncludeModule (string moduleFile)
209 return builder_extra.AddModule (moduleFile);
213 public override ModuleBuilder CreateModuleBuilder ()
215 if (file_name == null)
216 return Builder.DefineDynamicModule (Name, false);
218 return base.CreateModuleBuilder ();
222 // Initializes the code generator
224 public bool Create (AppDomain domain, AssemblyBuilderAccess access)
227 throw new NotSupportedException ();
229 ResolveAssemblySecurityAttributes ();
230 var an = CreateAssemblyName ();
232 Builder = file_name == null ?
233 domain.DefineDynamicAssembly (an, access) :
234 domain.DefineDynamicAssembly (an, access, Dirname (file_name));
236 module.Create (this, CreateModuleBuilder ());
237 builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
242 static string Dirname (string name)
244 int pos = name.LastIndexOf ('/');
247 return name.Substring (0, pos);
249 pos = name.LastIndexOf ('\\');
251 return name.Substring (0, pos);
257 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
260 var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
261 var set_module_only = module_only.GetSetMethod (true);
263 set_module_only.Invoke (Builder, new object[] { true });
265 base.SaveModule (pekind, machine);
268 Builder.Save (file_name, pekind, machine);
274 // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
277 class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension
279 static MethodInfo adder_method;
280 static MethodInfo add_permission;
281 static MethodInfo add_type_forwarder;
282 static MethodInfo win32_icon_define;
283 static FieldInfo assembly_version;
284 static FieldInfo assembly_algorithm;
285 static FieldInfo assembly_culture;
286 static FieldInfo assembly_flags;
288 AssemblyBuilder builder;
290 public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx)
296 public override Module AddModule (string module)
299 if (adder_method == null)
300 adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic);
302 return (Module) adder_method.Invoke (builder, new object[] { module });
304 return base.AddModule (module);
308 public override void AddPermissionRequests (PermissionSet[] permissions)
311 if (add_permission == null)
312 add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
314 add_permission.Invoke (builder, permissions);
316 base.AddPermissionRequests (permissions);
320 public override void AddTypeForwarder (TypeSpec type, Location loc)
323 if (add_type_forwarder == null) {
324 add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance);
327 add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () });
329 base.AddTypeForwarder (type, loc);
333 public override void DefineWin32IconResource (string fileName)
336 if (win32_icon_define == null)
337 win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic);
339 win32_icon_define.Invoke (builder, new object[] { fileName });
341 base.DefineWin32IconResource (fileName);
345 public override void SetAlgorithmId (uint value, Location loc)
348 if (assembly_algorithm == null)
349 assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
351 assembly_algorithm.SetValue (builder, value);
353 base.SetAlgorithmId (value, loc);
357 public override void SetCulture (string culture, Location loc)
360 if (assembly_culture == null)
361 assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
363 assembly_culture.SetValue (builder, culture);
365 base.SetCulture (culture, loc);
369 public override void SetFlags (uint flags, Location loc)
372 if (assembly_flags == null)
373 assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
375 assembly_flags.SetValue (builder, flags);
377 base.SetFlags (flags, loc);
381 public override void SetVersion (Version version, Location loc)
384 if (assembly_version == null)
385 assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
387 assembly_version.SetValue (builder, version.ToString (4));
389 base.SetVersion (version, loc);
395 // Reflection based references loader
397 class DynamicLoader : AssemblyReferencesLoader<Assembly>
399 readonly ReflectionImporter importer;
401 public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
404 paths.Add (GetSystemDir ());
406 this.importer = importer;
409 public ReflectionImporter Importer {
415 protected override string[] GetDefaultReferences ()
418 // For now the "default config" is harcoded into the compiler
419 // we can move this outside later
421 var default_references = new List<string> (8);
423 default_references.Add ("System");
424 default_references.Add ("System.Xml");
426 default_references.Add ("System.Net");
427 default_references.Add ("System.Windows");
428 default_references.Add ("System.Windows.Browser");
431 if (compiler.Settings.Version > LanguageVersion.ISO_2)
432 default_references.Add ("System.Core");
433 if (compiler.Settings.Version > LanguageVersion.V_3)
434 default_references.Add ("Microsoft.CSharp");
436 return default_references.ToArray ();
440 // Returns the directory where the system assemblies are installed
442 static string GetSystemDir ()
444 return Path.GetDirectoryName (typeof (object).Assembly.Location);
447 public override bool HasObjectType (Assembly assembly)
449 return assembly.GetType (compiler.BuildinTypes.Object.FullName) != null;
452 public override Assembly LoadAssemblyFile (string fileName)
454 return LoadAssemblyFile (fileName, false);
457 Assembly LoadAssemblyFile (string assembly, bool soft)
463 char[] path_chars = { '/', '\\' };
465 if (assembly.IndexOfAny (path_chars) != -1) {
466 a = Assembly.LoadFrom (assembly);
468 string ass = assembly;
469 if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
470 ass = assembly.Substring (0, assembly.Length - 4);
471 a = Assembly.Load (ass);
473 } catch (FileNotFoundException) {
475 foreach (string dir in paths) {
476 string full_path = Path.Combine (dir, assembly);
477 if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
481 a = Assembly.LoadFrom (full_path);
484 } catch (FileNotFoundException) {
489 Error_FileNotFound (assembly);
493 } catch (BadImageFormatException) {
494 Error_FileCorrupted (assembly);
500 public override Assembly LoadAssemblyDefault (string fileName)
502 return LoadAssemblyFile (fileName, true);
505 Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module)
507 string total_log = "";
511 return assembly.IncludeModule (module);
512 } catch (FileNotFoundException) {
514 foreach (string dir in paths) {
515 string full_path = Path.Combine (dir, module);
516 if (!module.EndsWith (".netmodule"))
517 full_path += ".netmodule";
520 return assembly.IncludeModule (full_path);
521 } catch (FileNotFoundException ff) {
522 total_log += ff.FusionLog;
526 Error_FileNotFound (module);
530 } catch (BadImageFormatException) {
531 Error_FileCorrupted (module);
537 public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace)
539 foreach (var moduleName in compiler.Settings.Modules) {
540 var m = LoadModuleFile (assembly, moduleName);
544 var md = importer.ImportModule (m, targetNamespace);
545 assembly.AddModule (md);
549 public override void LoadReferences (ModuleContainer module)
552 List<Tuple<RootNamespace, Assembly>> loaded;
553 base.LoadReferencesCore (module, out corlib, out loaded);
558 importer.ImportAssembly (corlib, module.GlobalRootNamespace);
559 foreach (var entry in loaded) {
560 importer.ImportAssembly (entry.Item2, entry.Item1);