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 (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 class ReflectionImporter : MetadataImporter
48 public ReflectionImporter (BuildinTypes buildin)
53 protected override MemberKind DetermineKindFromBaseType (Type baseType)
55 if (baseType == typeof (ValueType))
56 return MemberKind.Struct;
58 if (baseType == typeof (System.Enum))
59 return MemberKind.Enum;
61 if (baseType == typeof (MulticastDelegate))
62 return MemberKind.Delegate;
64 return MemberKind.Class;
67 protected override bool HasVolatileModifier (FieldInfo field)
69 var reqs = field.GetRequiredCustomModifiers ();
70 if (reqs.Length > 0) {
71 foreach (var t in reqs) {
72 if (t == typeof (IsVolatile))
80 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
82 // It can be used more than once when importing same assembly
83 // into 2 or more global aliases
84 var definition = GetAssemblyDefinition (assembly);
87 // This part tries to simulate loading of top-level
88 // types only, any missing dependencies are ignores here.
89 // Full error report is reported later when the type is
94 all_types = assembly.GetTypes ();
95 } catch (ReflectionTypeLoadException e) {
99 ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
102 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
104 var module_definition = new ImportedModuleDefinition (module, this);
105 module_definition.ReadAttributes ();
109 all_types = module.GetTypes ();
110 } catch (ReflectionTypeLoadException e) {
114 ImportTypes (all_types, targetNamespace, false);
116 return module_definition;
119 void Initialize (BuildinTypes buildin)
122 // Setup mapping for build-in types to avoid duplication of their definition
124 buildin_types.Add (typeof (object), buildin.Object);
125 buildin_types.Add (typeof (System.ValueType), buildin.ValueType);
126 buildin_types.Add (typeof (System.Attribute), buildin.Attribute);
128 buildin_types.Add (typeof (int), buildin.Int);
129 buildin_types.Add (typeof (long), buildin.Long);
130 buildin_types.Add (typeof (uint), buildin.UInt);
131 buildin_types.Add (typeof (ulong), buildin.ULong);
132 buildin_types.Add (typeof (byte), buildin.Byte);
133 buildin_types.Add (typeof (sbyte), buildin.SByte);
134 buildin_types.Add (typeof (short), buildin.Short);
135 buildin_types.Add (typeof (ushort), buildin.UShort);
137 buildin_types.Add (typeof (System.Collections.IEnumerator), buildin.IEnumerator);
138 buildin_types.Add (typeof (System.Collections.IEnumerable), buildin.IEnumerable);
139 buildin_types.Add (typeof (System.IDisposable), buildin.IDisposable);
141 buildin_types.Add (typeof (char), buildin.Char);
142 buildin_types.Add (typeof (string), buildin.String);
143 buildin_types.Add (typeof (float), buildin.Float);
144 buildin_types.Add (typeof (double), buildin.Double);
145 buildin_types.Add (typeof (decimal), buildin.Decimal);
146 buildin_types.Add (typeof (bool), buildin.Bool);
147 buildin_types.Add (typeof (System.IntPtr), buildin.IntPtr);
148 buildin_types.Add (typeof (System.UIntPtr), buildin.UIntPtr);
150 buildin_types.Add (typeof (System.MulticastDelegate), buildin.MulticastDelegate);
151 buildin_types.Add (typeof (System.Delegate), buildin.Delegate);
152 buildin_types.Add (typeof (System.Enum), buildin.Enum);
153 buildin_types.Add (typeof (System.Array), buildin.Array);
154 buildin_types.Add (typeof (void), buildin.Void);
155 buildin_types.Add (typeof (System.Type), buildin.Type);
156 buildin_types.Add (typeof (System.Exception), buildin.Exception);
157 buildin_types.Add (typeof (System.RuntimeFieldHandle), buildin.RuntimeFieldHandle);
158 buildin_types.Add (typeof (System.RuntimeTypeHandle), buildin.RuntimeTypeHandle);
163 public class AssemblyDefinitionDynamic : AssemblyDefinition
166 // In-memory only assembly container
168 public AssemblyDefinitionDynamic (ModuleContainer module, string name)
169 : base (module, name)
174 // Assembly container with file output
176 public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName)
177 : base (module, name, fileName)
181 public Module IncludeModule (string moduleFile)
183 return builder_extra.AddModule (moduleFile);
187 public override ModuleBuilder CreateModuleBuilder ()
189 if (file_name == null)
190 return Builder.DefineDynamicModule (Name, false);
192 return base.CreateModuleBuilder ();
196 // Initializes the code generator
198 public bool Create (AppDomain domain, AssemblyBuilderAccess access)
201 throw new NotSupportedException ();
203 ResolveAssemblySecurityAttributes ();
204 var an = CreateAssemblyName ();
207 Builder = file_name == null ?
208 domain.DefineDynamicAssembly (an, access) :
209 domain.DefineDynamicAssembly (an, access, Dirname (file_name));
210 } catch (ArgumentException) {
211 // specified key may not be exportable outside it's container
212 if (RootContext.StrongNameKeyContainer != null) {
213 Report.Error (1548, "Could not access the key inside the container `" +
214 RootContext.StrongNameKeyContainer + "'.");
219 builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
224 static string Dirname (string name)
226 int pos = name.LastIndexOf ('/');
229 return name.Substring (0, pos);
231 pos = name.LastIndexOf ('\\');
233 return name.Substring (0, pos);
239 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
242 var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
243 var set_module_only = module_only.GetSetMethod (true);
245 set_module_only.Invoke (Builder, new object[] { true });
247 base.SaveModule (pekind, machine);
250 Builder.Save (file_name, pekind, machine);
256 // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
259 class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension
261 static MethodInfo adder_method;
262 static MethodInfo add_permission;
263 static MethodInfo add_type_forwarder;
264 static MethodInfo win32_icon_define;
265 static FieldInfo assembly_version;
266 static FieldInfo assembly_algorithm;
267 static FieldInfo assembly_culture;
268 static FieldInfo assembly_flags;
270 AssemblyBuilder builder;
272 public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx)
278 public override Module AddModule (string module)
281 if (adder_method == null)
282 adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic);
284 return (Module) adder_method.Invoke (builder, new object[] { module });
286 return base.AddModule (module);
290 public override void AddPermissionRequests (PermissionSet[] permissions)
293 if (add_permission == null)
294 add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
296 add_permission.Invoke (builder, permissions);
298 base.AddPermissionRequests (permissions);
302 public override void AddTypeForwarder (TypeSpec type, Location loc)
305 if (add_type_forwarder == null) {
306 add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance);
309 add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () });
311 base.AddTypeForwarder (type, loc);
315 public override void DefineWin32IconResource (string fileName)
318 if (win32_icon_define == null)
319 win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic);
321 win32_icon_define.Invoke (builder, new object[] { fileName });
323 base.DefineWin32IconResource (fileName);
327 public override void SetAlgorithmId (uint value, Location loc)
330 if (assembly_algorithm == null)
331 assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
333 assembly_algorithm.SetValue (builder, value);
335 base.SetAlgorithmId (value, loc);
339 public override void SetCulture (string culture, Location loc)
342 if (assembly_culture == null)
343 assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
345 assembly_culture.SetValue (builder, culture);
347 base.SetCulture (culture, loc);
351 public override void SetFlags (uint flags, Location loc)
354 if (assembly_flags == null)
355 assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
357 assembly_flags.SetValue (builder, flags);
359 base.SetFlags (flags, loc);
363 public override void SetVersion (Version version, Location loc)
366 if (assembly_version == null)
367 assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
369 assembly_version.SetValue (builder, version.ToString (4));
371 base.SetVersion (version, loc);
377 // Reflection based references loader
379 class DynamicLoader : AssemblyReferencesLoader<Assembly>
381 readonly ReflectionImporter importer;
383 public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
386 this.importer = importer;
389 public ReflectionImporter Importer {
395 public override bool HasObjectType (Assembly assembly)
397 return assembly.GetType (compiler.BuildinTypes.Object.FullName) != null;
400 protected override string[] GetDefaultReferences ()
403 // For now the "default config" is harcoded into the compiler
404 // we can move this outside later
406 var default_references = new List<string> (8);
408 default_references.Add ("System");
409 default_references.Add ("System.Xml");
411 default_references.Add ("System.Net");
412 default_references.Add ("System.Windows");
413 default_references.Add ("System.Windows.Browser");
416 if (RootContext.Version > LanguageVersion.ISO_2)
417 default_references.Add ("System.Core");
418 if (RootContext.Version > LanguageVersion.V_3)
419 default_references.Add ("Microsoft.CSharp");
421 return default_references.ToArray ();
424 public override Assembly LoadAssemblyFile (string fileName)
426 return LoadAssemblyFile (fileName, false);
429 Assembly LoadAssemblyFile (string assembly, bool soft)
432 string total_log = "";
436 char[] path_chars = { '/', '\\' };
438 if (assembly.IndexOfAny (path_chars) != -1) {
439 a = Assembly.LoadFrom (assembly);
441 string ass = assembly;
442 if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
443 ass = assembly.Substring (0, assembly.Length - 4);
444 a = Assembly.Load (ass);
446 } catch (FileNotFoundException) {
448 foreach (string dir in paths) {
449 string full_path = Path.Combine (dir, assembly);
450 if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
454 a = Assembly.LoadFrom (full_path);
457 } catch (FileNotFoundException ff) {
460 total_log += ff.FusionLog;
464 Error_FileNotFound (assembly);
468 } catch (BadImageFormatException) {
469 Error_FileCorrupted (assembly);
475 public override Assembly LoadAssemblyDefault (string fileName)
477 return LoadAssemblyFile (fileName, true);
480 Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module)
482 string total_log = "";
486 return assembly.IncludeModule (module);
487 } catch (FileNotFoundException) {
489 foreach (string dir in paths) {
490 string full_path = Path.Combine (dir, module);
491 if (!module.EndsWith (".netmodule"))
492 full_path += ".netmodule";
495 return assembly.IncludeModule (full_path);
496 } catch (FileNotFoundException ff) {
497 total_log += ff.FusionLog;
501 Error_FileNotFound (module);
505 } catch (BadImageFormatException) {
506 Error_FileCorrupted (module);
512 public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace)
514 if (RootContext.Modules.Count == 0)
517 foreach (var moduleName in RootContext.Modules) {
518 var m = LoadModuleFile (assembly, moduleName);
522 var md = importer.ImportModule (m, targetNamespace);
523 assembly.AddModule (md);
527 public override void LoadReferences (ModuleContainer module)
530 List<Tuple<RootNamespace, Assembly>> loaded;
531 base.LoadReferencesCore (module, out corlib, out loaded);
536 importer.ImportAssembly (corlib, module.GlobalRootNamespace);
537 foreach (var entry in loaded) {
538 importer.ImportAssembly (entry.Item2, entry.Item1);