2 // System.Reflection.Emit/AssemblyBuilder.cs
5 // Paolo Molaro (lupus@ximian.com)
7 // (C) 2001 Ximian, Inc. http://www.ximian.com
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Reflection;
35 using System.Resources;
37 using System.Security.Policy;
38 using System.Runtime.Serialization;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Collections;
42 using System.Collections.Generic;
43 using System.Runtime.InteropServices;
44 using System.Security;
45 using System.Security.Cryptography;
46 using System.Security.Permissions;
49 using Mono.Security.Cryptography;
51 namespace System.Reflection.Emit
53 internal enum NativeResourceType
61 internal struct RefEmitPermissionSet {
62 public SecurityAction action;
65 public RefEmitPermissionSet (SecurityAction action, string pset) {
71 internal struct MonoResource {
74 public string filename;
75 public ResourceAttributes attrs;
80 internal struct MonoWin32Resource {
86 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
87 this.res_type = res_type;
89 this.lang_id = lang_id;
94 internal class GenericInstanceKey {
99 internal GenericInstanceKey (Type gtd, Type[] args)
104 hash_code = gtd.GetHashCode ();
105 for (int i = 0; i < args.Length; ++i)
106 hash_code ^= args [i].GetHashCode ();
109 static bool IsBoundedVector (Type type) {
110 ArrayType at = type as ArrayType;
112 return at.GetEffectiveRank () == 1;
113 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
116 static bool TypeEquals (Type a, Type b) {
120 if (a.HasElementType) {
121 if (!b.HasElementType)
123 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
128 int rank = a.GetArrayRank ();
129 if (rank != b.GetArrayRank ())
131 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
133 } else if (a.IsByRef) {
136 } else if (a.IsPointer) {
143 if (a.IsGenericType) {
144 if (!b.IsGenericType)
146 if (a.IsGenericParameter)
148 if (a.IsGenericParameter) //previous test should have caught it
151 if (a.IsGenericTypeDefinition) {
152 if (!b.IsGenericTypeDefinition)
155 if (b.IsGenericTypeDefinition)
157 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
160 Type[] argsA = a.GetGenericArguments ();
161 Type[] argsB = b.GetGenericArguments ();
162 for (int i = 0; i < argsA.Length; ++i) {
163 if (!TypeEquals (argsA [i], argsB [i]))
170 Now only non-generic, non compound types are left. To properly deal with user
171 types we would have to call UnderlyingSystemType, but we let them have their
172 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
173 depend on proper UT canonicalization.
178 public override bool Equals (object obj)
180 GenericInstanceKey other = obj as GenericInstanceKey;
183 if (gtd != other.gtd)
185 for (int i = 0; i < args.Length; ++i) {
187 Type b = other.args [i];
189 We must cannonicalize as much as we can. Using equals means that some resulting types
190 won't have the exact same types as the argument ones.
191 For example, flyweight types used array, pointer and byref will should this behavior.
192 MCS seens to be resilient to this problem so hopefully this won't show up.
194 if (a != b && !a.Equals (b))
200 public override int GetHashCode ()
208 [ComDefaultInterface (typeof (_AssemblyBuilder))]
209 [ClassInterface (ClassInterfaceType.None)]
210 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
211 #pragma warning disable 169, 414
212 #region Sync with object-internals.h
213 private UIntPtr dynamic_assembly; /* GC-tracked */
214 private MethodInfo entry_point;
215 private ModuleBuilder[] modules;
218 private CustomAttributeBuilder[] cattrs;
219 private MonoResource[] resources;
225 PEFileKinds pekind = PEFileKinds.Dll;
228 Module[] loaded_modules;
229 MonoWin32Resource[] win32_resources;
230 private RefEmitPermissionSet[] permissions_minimum;
231 private RefEmitPermissionSet[] permissions_optional;
232 private RefEmitPermissionSet[] permissions_refused;
233 PortableExecutableKinds peKind;
234 ImageFileMachine machine;
235 bool corlib_internal;
236 Type[] type_forwarders;
239 #pragma warning restore 169, 414
241 internal Type corlib_object_type = typeof (System.Object);
242 internal Type corlib_value_type = typeof (System.ValueType);
243 internal Type corlib_enum_type = typeof (System.Enum);
244 internal Type corlib_void_type = typeof (void);
245 ArrayList resource_writers = null;
246 Win32VersionResource version_res;
249 private Mono.Security.StrongName sn;
250 NativeResourceType native_resource;
251 readonly bool is_compiler_context;
252 string versioninfo_culture;
253 Hashtable generic_instances = new Hashtable ();
255 [MethodImplAttribute(MethodImplOptions.InternalCall)]
256 private static extern void basic_init (AssemblyBuilder ab);
258 /* Keep this in sync with codegen.cs in mcs */
259 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
261 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
263 is_compiler_context = (access & COMPILER_ACCESS) != 0;
265 // remove Mono specific flag to allow enum check to pass
266 access &= ~COMPILER_ACCESS;
269 // only "Run" is supported by Silverlight
270 // however SMCS requires more than this but runs outside the CoreCLR sandbox
271 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
272 throw new ArgumentException ("access");
275 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
276 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
277 "Argument value {0} is not valid.", (int) access),
281 if ((access & AssemblyBuilderAccess.RunAndCollect) == AssemblyBuilderAccess.RunAndCollect)
282 throw new NotSupportedException ("RunAndCollect not yet supported.");
286 this.access = (uint)access;
287 flags = (uint) n.Flags;
289 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
290 if (IsSave && (directory == null || directory.Length == 0)) {
291 dir = Directory.GetCurrentDirectory ();
296 /* Set defaults from n */
297 if (n.CultureInfo != null) {
298 culture = n.CultureInfo.Name;
299 versioninfo_culture = n.CultureInfo.Name;
301 Version v = n.Version;
303 version = v.ToString ();
306 if (n.KeyPair != null) {
307 // full keypair is available (for signing)
308 sn = n.KeyPair.StrongName ();
310 // public key is available (for delay-signing)
311 byte[] pk = n.GetPublicKey ();
312 if ((pk != null) && (pk.Length > 0)) {
313 sn = new Mono.Security.StrongName (pk);
318 flags |= (uint) AssemblyNameFlags.PublicKey;
320 this.corlib_internal = corlib_internal;
322 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
324 foreach (byte pkb in sn.PublicKeyToken) {
325 string part = pkb.ToString("x2");
326 this.pktoken[pkti++] = (byte)part[0];
327 this.pktoken[pkti++] = (byte)part[1];
334 public override string CodeBase {
336 throw not_supported ();
340 public override MethodInfo EntryPoint {
346 public override string Location {
348 throw not_supported ();
352 /* This is to keep signature compatibility with MS.NET */
353 public override string ImageRuntimeVersion {
355 return base.ImageRuntimeVersion;
360 public override bool ReflectionOnly {
361 get { return base.ReflectionOnly; }
364 public void AddResourceFile (string name, string fileName)
366 AddResourceFile (name, fileName, ResourceAttributes.Public);
369 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
371 AddResourceFile (name, fileName, attribute, true);
374 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
376 check_name_and_filename (name, fileName, fileNeedsToExists);
378 // Resource files are created/searched under the assembly storage
381 fileName = Path.Combine (dir, fileName);
383 if (resources != null) {
384 MonoResource[] new_r = new MonoResource [resources.Length + 1];
385 System.Array.Copy(resources, new_r, resources.Length);
388 resources = new MonoResource [1];
390 int p = resources.Length - 1;
391 resources [p].name = name;
392 resources [p].filename = fileName;
393 resources [p].attrs = attribute;
397 /// Don't change the method name and parameters order. It is used by mcs
399 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
403 throw new InvalidOperationException ("Assembly was already saved.");
405 // required for base Assembly class (so the permissions
406 // can be used even if the assembly isn't saved to disk)
408 _optional = optional;
411 // required to reuse AddDeclarativeSecurity support
412 // already present in the runtime
413 if (required != null) {
414 permissions_minimum = new RefEmitPermissionSet [1];
415 permissions_minimum [0] = new RefEmitPermissionSet (
416 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
418 if (optional != null) {
419 permissions_optional = new RefEmitPermissionSet [1];
420 permissions_optional [0] = new RefEmitPermissionSet (
421 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
423 if (refused != null) {
424 permissions_refused = new RefEmitPermissionSet [1];
425 permissions_refused [0] = new RefEmitPermissionSet (
426 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
431 // Still in use by al.exe
432 internal void EmbedResourceFile (string name, string fileName)
434 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
437 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
439 if (resources != null) {
440 MonoResource[] new_r = new MonoResource [resources.Length + 1];
441 System.Array.Copy(resources, new_r, resources.Length);
444 resources = new MonoResource [1];
446 int p = resources.Length - 1;
447 resources [p].name = name;
448 resources [p].attrs = attribute;
450 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
452 resources [p].data = new byte [len];
453 s.Read (resources [p].data, 0, (int)len);
459 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
461 if (resources != null) {
462 MonoResource[] new_r = new MonoResource [resources.Length + 1];
463 System.Array.Copy(resources, new_r, resources.Length);
466 resources = new MonoResource [1];
468 int p = resources.Length - 1;
469 resources [p].name = name;
470 resources [p].attrs = attribute;
471 resources [p].data = blob;
474 internal void AddTypeForwarder (Type t) {
476 throw new ArgumentNullException ("t");
478 throw new ArgumentException ();
480 if (type_forwarders == null) {
481 type_forwarders = new Type [1] { t };
483 Type[] arr = new Type [type_forwarders.Length + 1];
484 Array.Copy (type_forwarders, arr, type_forwarders.Length);
485 arr [type_forwarders.Length] = t;
486 type_forwarders = arr;
490 public ModuleBuilder DefineDynamicModule (string name)
492 return DefineDynamicModule (name, name, false, true);
495 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
497 return DefineDynamicModule (name, name, emitSymbolInfo, true);
500 public ModuleBuilder DefineDynamicModule(string name, string fileName)
502 return DefineDynamicModule (name, fileName, false, false);
505 public ModuleBuilder DefineDynamicModule (string name, string fileName,
508 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
511 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
513 check_name_and_filename (name, fileName, false);
516 if (Path.GetExtension (fileName) == String.Empty)
517 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
519 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
521 throw new InvalidOperationException ("Assembly was already saved.");
524 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
526 if ((modules != null) && is_module_only)
527 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
529 if (modules != null) {
530 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
531 System.Array.Copy(modules, new_modules, modules.Length);
532 modules = new_modules;
534 modules = new ModuleBuilder [1];
536 modules [modules.Length - 1] = r;
540 [MethodImplAttribute(MethodImplOptions.InternalCall)]
541 private extern Module InternalAddModule (string fileName);
544 * Mono extension to support /addmodule in mcs.
546 internal Module AddModule (string fileName)
548 if (fileName == null)
549 throw new ArgumentNullException (fileName);
551 Module m = InternalAddModule (fileName);
553 if (loaded_modules != null) {
554 Module[] new_modules = new Module [loaded_modules.Length + 1];
555 System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
556 loaded_modules = new_modules;
558 loaded_modules = new Module [1];
560 loaded_modules [loaded_modules.Length - 1] = m;
565 public IResourceWriter DefineResource (string name, string description, string fileName)
567 return DefineResource (name, description, fileName, ResourceAttributes.Public);
570 public IResourceWriter DefineResource (string name, string description,
571 string fileName, ResourceAttributes attribute)
573 IResourceWriter writer;
575 // description seems to be ignored
576 AddResourceFile (name, fileName, attribute, false);
577 writer = new ResourceWriter (fileName);
578 if (resource_writers == null)
579 resource_writers = new ArrayList ();
580 resource_writers.Add (writer);
584 private void AddUnmanagedResource (Win32Resource res) {
585 MemoryStream ms = new MemoryStream ();
588 if (win32_resources != null) {
589 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
590 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
591 win32_resources = new_res;
594 win32_resources = new MonoWin32Resource [1];
596 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
599 [MonoTODO ("Not currently implemenented")]
600 public void DefineUnmanagedResource (byte[] resource)
602 if (resource == null)
603 throw new ArgumentNullException ("resource");
604 if (native_resource != NativeResourceType.None)
605 throw new ArgumentException ("Native resource has already been defined.");
607 // avoid definition of more than one unmanaged resource
608 native_resource = NativeResourceType.Unmanaged;
611 * The format of the argument byte array is not documented
612 * so this method is impossible to implement.
614 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
617 throw new NotImplementedException ();
620 public void DefineUnmanagedResource (string resourceFileName)
622 if (resourceFileName == null)
623 throw new ArgumentNullException ("resourceFileName");
624 if (resourceFileName.Length == 0)
625 throw new ArgumentException ("resourceFileName");
626 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
627 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
628 if (native_resource != NativeResourceType.None)
629 throw new ArgumentException ("Native resource has already been defined.");
631 // avoid definition of more than one unmanaged resource
632 native_resource = NativeResourceType.Unmanaged;
634 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
635 Win32ResFileReader reader = new Win32ResFileReader (fs);
637 foreach (Win32EncodedResource res in reader.ReadResources ()) {
638 if (res.Name.IsName || res.Type.IsName)
639 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
641 AddUnmanagedResource (res);
646 public void DefineVersionInfoResource ()
648 if (native_resource != NativeResourceType.None)
649 throw new ArgumentException ("Native resource has already been defined.");
651 // avoid definition of more than one unmanaged resource
652 native_resource = NativeResourceType.Assembly;
654 version_res = new Win32VersionResource (1, 0, IsCompilerContext);
657 public void DefineVersionInfoResource (string product, string productVersion,
658 string company, string copyright, string trademark)
660 if (native_resource != NativeResourceType.None)
661 throw new ArgumentException ("Native resource has already been defined.");
663 // avoid definition of more than one unmanaged resource
664 native_resource = NativeResourceType.Explicit;
667 * We can only create the resource later, when the file name and
668 * the binary version is known.
671 version_res = new Win32VersionResource (1, 0, false);
672 version_res.ProductName = product != null ? product : " ";
673 version_res.ProductVersion = productVersion != null ? productVersion : " ";
674 version_res.CompanyName = company != null ? company : " ";
675 version_res.LegalCopyright = copyright != null ? copyright : " ";
676 version_res.LegalTrademarks = trademark != null ? trademark : " ";
680 * Mono extension to support /win32icon in mcs
682 internal void DefineIconResource (string iconFileName)
684 if (iconFileName == null)
685 throw new ArgumentNullException ("iconFileName");
686 if (iconFileName.Length == 0)
687 throw new ArgumentException ("iconFileName");
688 if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
689 throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
691 using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
692 Win32IconFileReader reader = new Win32IconFileReader (fs);
694 ICONDIRENTRY[] entries = reader.ReadIcons ();
696 Win32IconResource[] icons = new Win32IconResource [entries.Length];
697 for (int i = 0; i < entries.Length; ++i) {
698 icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
699 AddUnmanagedResource (icons [i]);
702 Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
703 AddUnmanagedResource (group);
707 private void DefineVersionInfoResourceImpl (string fileName)
709 if (versioninfo_culture != null)
710 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
711 version_res.Version = version == null ? "0.0.0.0" : version;
713 if (cattrs != null) {
714 switch (native_resource) {
715 case NativeResourceType.Assembly:
716 foreach (CustomAttributeBuilder cb in cattrs) {
717 string attrname = cb.Ctor.ReflectedType.FullName;
719 if (attrname == "System.Reflection.AssemblyProductAttribute")
720 version_res.ProductName = cb.string_arg ();
721 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
722 version_res.CompanyName = cb.string_arg ();
723 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
724 version_res.LegalCopyright = cb.string_arg ();
725 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
726 version_res.LegalTrademarks = cb.string_arg ();
727 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
728 if (!IsCompilerContext)
729 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
730 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
731 string fileversion = cb.string_arg ();
732 if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
733 version_res.FileVersion = fileversion;
734 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
735 version_res.ProductVersion = cb.string_arg ();
736 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
737 version_res.FileDescription = cb.string_arg ();
738 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
739 version_res.Comments = cb.string_arg ();
742 case NativeResourceType.Explicit:
743 foreach (CustomAttributeBuilder cb in cattrs) {
744 string attrname = cb.Ctor.ReflectedType.FullName;
746 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
747 if (!IsCompilerContext)
748 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
749 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
750 version_res.Comments = cb.string_arg ();
756 version_res.OriginalFilename = fileName;
758 if (IsCompilerContext) {
759 version_res.InternalName = fileName;
760 if (version_res.ProductVersion.Trim ().Length == 0)
761 version_res.ProductVersion = version_res.FileVersion;
763 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
766 AddUnmanagedResource (version_res);
769 public ModuleBuilder GetDynamicModule (string name)
772 throw new ArgumentNullException ("name");
773 if (name.Length == 0)
774 throw new ArgumentException ("Empty name is not legal.", "name");
777 for (int i = 0; i < modules.Length; ++i)
778 if (modules [i].name == name)
783 public override Type[] GetExportedTypes ()
785 throw not_supported ();
788 public override FileStream GetFile (string name)
790 throw not_supported ();
793 public override FileStream[] GetFiles(bool getResourceModules) {
794 throw not_supported ();
797 internal override Module[] GetModulesInternal () {
799 return new Module [0];
801 return (Module[])modules.Clone ();
804 internal override Type[] GetTypes (bool exportedOnly) {
806 if (modules != null) {
807 for (int i = 0; i < modules.Length; ++i) {
808 Type[] types = modules [i].GetTypes ();
812 Type[] tmp = new Type [res.Length + types.Length];
813 Array.Copy (res, 0, tmp, 0, res.Length);
814 Array.Copy (types, 0, tmp, res.Length, types.Length);
818 if (loaded_modules != null) {
819 for (int i = 0; i < loaded_modules.Length; ++i) {
820 Type[] types = loaded_modules [i].GetTypes ();
824 Type[] tmp = new Type [res.Length + types.Length];
825 Array.Copy (res, 0, tmp, 0, res.Length);
826 Array.Copy (types, 0, tmp, res.Length, types.Length);
832 List<Exception> exceptions = null;
833 foreach (var type in res) {
834 if (type is TypeBuilder) {
835 if (exceptions == null)
836 exceptions = new List <Exception> ();
837 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
840 if (exceptions != null)
841 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
844 return res == null ? Type.EmptyTypes : res;
847 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
848 throw not_supported ();
851 public override string[] GetManifestResourceNames() {
852 throw not_supported ();
855 public override Stream GetManifestResourceStream(string name) {
856 throw not_supported ();
858 public override Stream GetManifestResourceStream(Type type, string name) {
859 throw not_supported ();
863 * This is set when the the AssemblyBuilder is created by (g)mcs
866 internal bool IsCompilerContext
868 get { return is_compiler_context; }
871 internal bool IsSave {
873 return access != (uint)AssemblyBuilderAccess.Run;
877 internal bool IsRun {
879 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
881 || access == (uint)AssemblyBuilderAccess.RunAndCollect
888 internal string AssemblyDir {
895 * Mono extension. If this is set, the assembly can only contain one
896 * module, access should be Save, and the saved image will not contain an
899 internal bool IsModuleOnly {
901 return is_module_only;
904 is_module_only = value;
908 ModuleBuilder manifest_module;
911 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
912 // on an assemblybuilder.
914 internal override Module GetManifestModule () {
915 if (manifest_module == null)
916 manifest_module = DefineDynamicModule ("Default Dynamic Module");
917 return manifest_module;
920 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
922 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
924 this.peKind = portableExecutableKind;
925 this.machine = imageFileMachine;
927 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
928 throw new NotImplementedException (peKind.ToString ());
929 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
930 throw new NotImplementedException (machine.ToString ());
932 if (resource_writers != null) {
933 foreach (IResourceWriter writer in resource_writers) {
939 // Create a main module if not already created
940 ModuleBuilder mainModule = null;
941 if (modules != null) {
942 foreach (ModuleBuilder module in modules)
943 if (module.FullyQualifiedName == assemblyFileName)
946 if (mainModule == null)
947 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
950 mainModule.IsMain = true;
953 * Create a new entry point if the one specified
954 * by the user is in another module.
956 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
958 if (entry_point.GetParameters ().Length == 1)
959 paramTypes = new Type [] { typeof (string) };
961 paramTypes = Type.EmptyTypes;
963 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
964 ILGenerator ilgen = mb.GetILGenerator ();
965 if (paramTypes.Length == 1)
966 ilgen.Emit (OpCodes.Ldarg_0);
967 ilgen.Emit (OpCodes.Tailcall);
968 ilgen.Emit (OpCodes.Call, entry_point);
969 ilgen.Emit (OpCodes.Ret);
974 if (version_res != null)
975 DefineVersionInfoResourceImpl (assemblyFileName);
978 // runtime needs to value to embed it into the assembly
979 public_key = sn.PublicKey;
982 foreach (ModuleBuilder module in modules)
983 if (module != mainModule)
986 // Write out the main module at the end, because it needs to
987 // contain the hash of the other modules
990 if ((sn != null) && (sn.CanSign)) {
991 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
997 public void Save (string assemblyFileName)
999 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
1002 public void SetEntryPoint (MethodInfo entryMethod)
1004 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
1007 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
1009 if (entryMethod == null)
1010 throw new ArgumentNullException ("entryMethod");
1011 if (entryMethod.DeclaringType.Assembly != this)
1012 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
1014 entry_point = entryMethod;
1018 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
1020 if (customBuilder == null)
1021 throw new ArgumentNullException ("customBuilder");
1023 if (IsCompilerContext) {
1024 string attrname = customBuilder.Ctor.ReflectedType.FullName;
1028 if (attrname == "System.Reflection.AssemblyVersionAttribute") {
1029 version = create_assembly_version (customBuilder.string_arg ());
1031 } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
1032 culture = GetCultureString (customBuilder.string_arg ());
1033 } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
1034 data = customBuilder.Data;
1036 algid = (uint) data [pos];
1037 algid |= ((uint) data [pos + 1]) << 8;
1038 algid |= ((uint) data [pos + 2]) << 16;
1039 algid |= ((uint) data [pos + 3]) << 24;
1040 } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
1041 data = customBuilder.Data;
1043 flags |= (uint) data [pos];
1044 flags |= ((uint) data [pos + 1]) << 8;
1045 flags |= ((uint) data [pos + 2]) << 16;
1046 flags |= ((uint) data [pos + 3]) << 24;
1048 // ignore PublicKey flag if assembly is not strongnamed
1050 flags &= ~(uint) AssemblyNameFlags.PublicKey;
1054 if (cattrs != null) {
1055 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
1056 cattrs.CopyTo (new_array, 0);
1057 new_array [cattrs.Length] = customBuilder;
1060 cattrs = new CustomAttributeBuilder [1];
1061 cattrs [0] = customBuilder;
1066 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
1068 throw new ArgumentNullException ("con");
1069 if (binaryAttribute == null)
1070 throw new ArgumentNullException ("binaryAttribute");
1072 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
1075 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
1076 this.corlib_object_type = corlib_object_type;
1077 this.corlib_value_type = corlib_value_type;
1078 this.corlib_enum_type = corlib_enum_type;
1081 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
1083 SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
1084 this.corlib_void_type = corlib_void_type;
1087 private Exception not_supported () {
1088 // Strange message but this is what MS.NET prints...
1089 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
1092 private void check_name_and_filename (string name, string fileName,
1093 bool fileNeedsToExists) {
1095 throw new ArgumentNullException ("name");
1096 if (fileName == null)
1097 throw new ArgumentNullException ("fileName");
1098 if (name.Length == 0)
1099 throw new ArgumentException ("Empty name is not legal.", "name");
1100 if (fileName.Length == 0)
1101 throw new ArgumentException ("Empty file name is not legal.", "fileName");
1102 if (Path.GetFileName (fileName) != fileName)
1103 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
1105 // Resource files are created/searched under the assembly storage
1107 string fullFileName = fileName;
1109 fullFileName = Path.Combine (dir, fileName);
1111 if (fileNeedsToExists && !File.Exists (fullFileName))
1112 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
1114 if (resources != null) {
1115 for (int i = 0; i < resources.Length; ++i) {
1116 if (resources [i].filename == fullFileName)
1117 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1118 if (resources [i].name == name)
1119 throw new ArgumentException ("Duplicate name '" + name + "'");
1123 if (modules != null) {
1124 for (int i = 0; i < modules.Length; ++i) {
1125 // Use fileName instead of fullFileName here
1126 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1127 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1128 if (modules [i].Name == name)
1129 throw new ArgumentException ("Duplicate name '" + name + "'");
1134 private String create_assembly_version (String version) {
1135 String[] parts = version.Split ('.');
1136 int[] ver = new int [4] { 0, 0, 0, 0 };
1138 if ((parts.Length < 0) || (parts.Length > 4))
1139 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1141 for (int i = 0; i < parts.Length; ++i) {
1142 if (parts [i] == "*") {
1143 DateTime now = DateTime.Now;
1146 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1147 if (parts.Length == 3)
1148 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1152 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1154 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1158 ver [i] = Int32.Parse (parts [i]);
1160 catch (FormatException) {
1161 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1166 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1169 private string GetCultureString (string str)
1171 return (str == "neutral" ? String.Empty : str);
1174 internal override AssemblyName UnprotectedGetName ()
1176 AssemblyName an = base.UnprotectedGetName ();
1178 an.SetPublicKey (sn.PublicKey);
1179 an.SetPublicKeyToken (sn.PublicKeyToken);
1184 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1185 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1187 if (!IsCompilerContext)
1188 return new MonoGenericClass (gtd, typeArguments);
1190 GenericInstanceKey key = new GenericInstanceKey (gtd, typeArguments);
1191 MonoGenericClass res = (MonoGenericClass)generic_instances [key];
1193 res = new MonoGenericClass (gtd, typeArguments);
1194 generic_instances [key] = res;
1199 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1201 throw new NotImplementedException ();
1204 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1206 throw new NotImplementedException ();
1209 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1211 throw new NotImplementedException ();
1214 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1216 throw new NotImplementedException ();
1219 #if NET_4_0 || MOONLIGHT
1220 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1223 throw new ArgumentNullException (name);
1224 if (name.Length == 0)
1225 throw new ArgumentException ("name", "Name cannot be empty");
1227 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1228 if (res is TypeBuilder) {
1230 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1236 public override Module GetModule (String name)
1239 throw new ArgumentNullException ("name");
1240 if (name.Length == 0)
1241 throw new ArgumentException ("Name can't be empty");
1243 if (modules == null)
1246 foreach (Module module in modules) {
1247 if (module.ScopeName == name)
1254 public override Module[] GetModules (bool getResourceModules)
1256 Module[] modules = GetModulesInternal ();
1258 if (!getResourceModules) {
1259 ArrayList result = new ArrayList (modules.Length);
1260 foreach (Module m in modules)
1261 if (!m.IsResource ())
1263 return (Module[])result.ToArray (typeof (Module));
1268 [MonoTODO ("This always returns an empty array")]
1269 public override AssemblyName[] GetReferencedAssemblies () {
1270 return GetReferencedAssemblies (this);
1273 public override Module[] GetLoadedModules (bool getResourceModules)
1275 return GetModules (getResourceModules);
1278 //FIXME MS has issues loading satelite assemblies from SRE
1279 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1281 return GetSatelliteAssembly (culture, null, true);
1284 //FIXME MS has issues loading satelite assemblies from SRE
1285 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1287 return GetSatelliteAssembly (culture, version, true);
1290 public override Module ManifestModule {
1292 return GetManifestModule ();
1296 public override bool GlobalAssemblyCache {
1302 public override bool IsDynamic {
1303 get { return true; }