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, BuiltinTypes builtin)
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, BuiltinTypes builtin)
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 protected override bool HasVolatileModifier (Type[] modifiers)
74 foreach (var t in modifiers) {
75 if (t == typeof (IsVolatile))
82 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
84 // It can be used more than once when importing same assembly
85 // into 2 or more global aliases
86 GetAssemblyDefinition (assembly);
89 // This part tries to simulate loading of top-level
90 // types only, any missing dependencies are ignores here.
91 // Full error report is reported later when the type is
96 all_types = assembly.GetTypes ();
97 } catch (ReflectionTypeLoadException e) {
101 ImportTypes (all_types, targetNamespace, true);
104 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
106 var module_definition = new ImportedModuleDefinition (module);
107 module_definition.ReadAttributes ();
111 all_types = module.GetTypes ();
112 } catch (ReflectionTypeLoadException e) {
116 ImportTypes (all_types, targetNamespace, false);
118 return module_definition;
121 void Initialize (BuiltinTypes builtin)
124 // Setup mapping for build-in types to avoid duplication of their definition
126 compiled_types.Add (typeof (object), builtin.Object);
127 compiled_types.Add (typeof (System.ValueType), builtin.ValueType);
128 compiled_types.Add (typeof (System.Attribute), builtin.Attribute);
130 compiled_types.Add (typeof (int), builtin.Int);
131 compiled_types.Add (typeof (long), builtin.Long);
132 compiled_types.Add (typeof (uint), builtin.UInt);
133 compiled_types.Add (typeof (ulong), builtin.ULong);
134 compiled_types.Add (typeof (byte), builtin.Byte);
135 compiled_types.Add (typeof (sbyte), builtin.SByte);
136 compiled_types.Add (typeof (short), builtin.Short);
137 compiled_types.Add (typeof (ushort), builtin.UShort);
139 compiled_types.Add (typeof (System.Collections.IEnumerator), builtin.IEnumerator);
140 compiled_types.Add (typeof (System.Collections.IEnumerable), builtin.IEnumerable);
141 compiled_types.Add (typeof (System.IDisposable), builtin.IDisposable);
143 compiled_types.Add (typeof (char), builtin.Char);
144 compiled_types.Add (typeof (string), builtin.String);
145 compiled_types.Add (typeof (float), builtin.Float);
146 compiled_types.Add (typeof (double), builtin.Double);
147 compiled_types.Add (typeof (decimal), builtin.Decimal);
148 compiled_types.Add (typeof (bool), builtin.Bool);
149 compiled_types.Add (typeof (System.IntPtr), builtin.IntPtr);
150 compiled_types.Add (typeof (System.UIntPtr), builtin.UIntPtr);
152 compiled_types.Add (typeof (System.MulticastDelegate), builtin.MulticastDelegate);
153 compiled_types.Add (typeof (System.Delegate), builtin.Delegate);
154 compiled_types.Add (typeof (System.Enum), builtin.Enum);
155 compiled_types.Add (typeof (System.Array), builtin.Array);
156 compiled_types.Add (typeof (void), builtin.Void);
157 compiled_types.Add (typeof (System.Type), builtin.Type);
158 compiled_types.Add (typeof (System.Exception), builtin.Exception);
159 compiled_types.Add (typeof (System.RuntimeFieldHandle), builtin.RuntimeFieldHandle);
160 compiled_types.Add (typeof (System.RuntimeTypeHandle), builtin.RuntimeTypeHandle);
164 [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)]
165 struct SingleConverter
167 [System.Runtime.InteropServices.FieldOffset (0)]
170 #pragma warning disable 414
171 [System.Runtime.InteropServices.FieldOffset (0)]
173 #pragma warning restore 414
175 public static int SingleToInt32Bits (float v)
177 SingleConverter c = new SingleConverter ();
185 public class AssemblyDefinitionDynamic : AssemblyDefinition
188 // In-memory only assembly container
190 public AssemblyDefinitionDynamic (ModuleContainer module, string name)
191 : base (module, name)
196 // Assembly container with file output
198 public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName)
199 : base (module, name, fileName)
203 public Module IncludeModule (string moduleFile)
205 return builder_extra.AddModule (moduleFile);
209 public override ModuleBuilder CreateModuleBuilder ()
211 if (file_name == null)
212 return Builder.DefineDynamicModule (Name, false);
214 return base.CreateModuleBuilder ();
218 // Initializes the code generator
220 public bool Create (AppDomain domain, AssemblyBuilderAccess access)
223 throw new NotSupportedException ();
225 ResolveAssemblySecurityAttributes ();
226 var an = CreateAssemblyName ();
228 Builder = file_name == null ?
229 domain.DefineDynamicAssembly (an, access) :
230 domain.DefineDynamicAssembly (an, access, Dirname (file_name));
232 module.Create (this, CreateModuleBuilder ());
233 builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
238 static string Dirname (string name)
240 int pos = name.LastIndexOf ('/');
243 return name.Substring (0, pos);
245 pos = name.LastIndexOf ('\\');
247 return name.Substring (0, pos);
253 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
256 var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
257 var set_module_only = module_only.GetSetMethod (true);
259 set_module_only.Invoke (Builder, new object[] { true });
261 base.SaveModule (pekind, machine);
264 Builder.Save (file_name, pekind, machine);
270 // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
273 class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension
275 static MethodInfo adder_method;
276 static MethodInfo add_permission;
277 static MethodInfo add_type_forwarder;
278 static MethodInfo win32_icon_define;
279 static FieldInfo assembly_version;
280 static FieldInfo assembly_algorithm;
281 static FieldInfo assembly_culture;
282 static FieldInfo assembly_flags;
284 AssemblyBuilder builder;
286 public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx)
292 public override Module AddModule (string module)
295 if (adder_method == null)
296 adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic);
298 return (Module) adder_method.Invoke (builder, new object[] { module });
300 return base.AddModule (module);
304 public override void AddPermissionRequests (PermissionSet[] permissions)
307 if (add_permission == null)
308 add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
310 add_permission.Invoke (builder, permissions);
312 base.AddPermissionRequests (permissions);
316 public override void AddTypeForwarder (TypeSpec type, Location loc)
319 if (add_type_forwarder == null) {
320 add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance);
323 add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () });
325 base.AddTypeForwarder (type, loc);
329 public override void DefineWin32IconResource (string fileName)
332 if (win32_icon_define == null)
333 win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic);
335 win32_icon_define.Invoke (builder, new object[] { fileName });
337 base.DefineWin32IconResource (fileName);
341 public override void SetAlgorithmId (uint value, Location loc)
344 if (assembly_algorithm == null)
345 assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
347 assembly_algorithm.SetValue (builder, value);
349 base.SetAlgorithmId (value, loc);
353 public override void SetCulture (string culture, Location loc)
356 if (assembly_culture == null)
357 assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
359 assembly_culture.SetValue (builder, culture);
361 base.SetCulture (culture, loc);
365 public override void SetFlags (uint flags, Location loc)
368 if (assembly_flags == null)
369 assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
371 assembly_flags.SetValue (builder, flags);
373 base.SetFlags (flags, loc);
377 public override void SetVersion (Version version, Location loc)
380 if (assembly_version == null)
381 assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
383 assembly_version.SetValue (builder, version.ToString (4));
385 base.SetVersion (version, loc);
391 // Reflection based references loader
393 class DynamicLoader : AssemblyReferencesLoader<Assembly>
395 readonly ReflectionImporter importer;
397 public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
400 paths.Add (GetSystemDir ());
402 this.importer = importer;
405 public ReflectionImporter Importer {
411 protected override string[] GetDefaultReferences ()
414 // For now the "default config" is harcoded into the compiler
415 // we can move this outside later
417 var default_references = new List<string> (8);
419 default_references.Add ("System");
420 default_references.Add ("System.Xml");
422 default_references.Add ("System.Net");
423 default_references.Add ("System.Windows");
424 default_references.Add ("System.Windows.Browser");
427 if (compiler.Settings.Version > LanguageVersion.ISO_2)
428 default_references.Add ("System.Core");
429 if (compiler.Settings.Version > LanguageVersion.V_3)
430 default_references.Add ("Microsoft.CSharp");
432 return default_references.ToArray ();
436 // Returns the directory where the system assemblies are installed
438 static string GetSystemDir ()
440 return Path.GetDirectoryName (typeof (object).Assembly.Location);
443 public override bool HasObjectType (Assembly assembly)
445 return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null;
448 public override Assembly LoadAssemblyFile (string assembly, bool isImplicitReference)
454 char[] path_chars = { '/', '\\' };
456 if (assembly.IndexOfAny (path_chars) != -1) {
457 a = Assembly.LoadFrom (assembly);
459 string ass = assembly;
460 if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
461 ass = assembly.Substring (0, assembly.Length - 4);
462 a = Assembly.Load (ass);
464 } catch (FileNotFoundException) {
465 bool err = !isImplicitReference;
466 foreach (string dir in paths) {
467 string full_path = Path.Combine (dir, assembly);
468 if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
472 a = Assembly.LoadFrom (full_path);
475 } catch (FileNotFoundException) {
480 Error_FileNotFound (assembly);
484 } catch (BadImageFormatException) {
485 Error_FileCorrupted (assembly);
491 Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module)
493 string total_log = "";
497 return assembly.IncludeModule (module);
498 } catch (FileNotFoundException) {
500 foreach (string dir in paths) {
501 string full_path = Path.Combine (dir, module);
502 if (!module.EndsWith (".netmodule"))
503 full_path += ".netmodule";
506 return assembly.IncludeModule (full_path);
507 } catch (FileNotFoundException ff) {
508 total_log += ff.FusionLog;
512 Error_FileNotFound (module);
516 } catch (BadImageFormatException) {
517 Error_FileCorrupted (module);
523 public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace)
525 foreach (var moduleName in compiler.Settings.Modules) {
526 var m = LoadModuleFile (assembly, moduleName);
530 var md = importer.ImportModule (m, targetNamespace);
531 assembly.AddModule (md);
535 public override void LoadReferences (ModuleContainer module)
538 List<Tuple<RootNamespace, Assembly>> loaded;
539 base.LoadReferencesCore (module, out corlib, out loaded);
544 importer.ImportAssembly (corlib, module.GlobalRootNamespace);
545 foreach (var entry in loaded) {
546 importer.ImportAssembly (entry.Item2, entry.Item1);