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 this.access = (uint)access;
282 flags = (uint) n.Flags;
284 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
285 if (IsSave && (directory == null || directory.Length == 0)) {
286 dir = Directory.GetCurrentDirectory ();
291 /* Set defaults from n */
292 if (n.CultureInfo != null) {
293 culture = n.CultureInfo.Name;
294 versioninfo_culture = n.CultureInfo.Name;
296 Version v = n.Version;
298 version = v.ToString ();
301 if (n.KeyPair != null) {
302 // full keypair is available (for signing)
303 sn = n.KeyPair.StrongName ();
305 // public key is available (for delay-signing)
306 byte[] pk = n.GetPublicKey ();
307 if ((pk != null) && (pk.Length > 0)) {
308 sn = new Mono.Security.StrongName (pk);
313 flags |= (uint) AssemblyNameFlags.PublicKey;
315 this.corlib_internal = corlib_internal;
317 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
319 foreach (byte pkb in sn.PublicKeyToken) {
320 string part = pkb.ToString("x2");
321 this.pktoken[pkti++] = (byte)part[0];
322 this.pktoken[pkti++] = (byte)part[1];
329 public override string CodeBase {
331 throw not_supported ();
335 public override MethodInfo EntryPoint {
341 public override string Location {
343 throw not_supported ();
347 /* This is to keep signature compatibility with MS.NET */
348 public override string ImageRuntimeVersion {
350 return base.ImageRuntimeVersion;
355 public override bool ReflectionOnly {
356 get { return base.ReflectionOnly; }
359 public void AddResourceFile (string name, string fileName)
361 AddResourceFile (name, fileName, ResourceAttributes.Public);
364 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
366 AddResourceFile (name, fileName, attribute, true);
369 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
371 check_name_and_filename (name, fileName, fileNeedsToExists);
373 // Resource files are created/searched under the assembly storage
376 fileName = Path.Combine (dir, fileName);
378 if (resources != null) {
379 MonoResource[] new_r = new MonoResource [resources.Length + 1];
380 System.Array.Copy(resources, new_r, resources.Length);
383 resources = new MonoResource [1];
385 int p = resources.Length - 1;
386 resources [p].name = name;
387 resources [p].filename = fileName;
388 resources [p].attrs = attribute;
392 /// Don't change the method name and parameters order. It is used by mcs
394 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
398 throw new InvalidOperationException ("Assembly was already saved.");
400 // required for base Assembly class (so the permissions
401 // can be used even if the assembly isn't saved to disk)
403 _optional = optional;
406 // required to reuse AddDeclarativeSecurity support
407 // already present in the runtime
408 if (required != null) {
409 permissions_minimum = new RefEmitPermissionSet [1];
410 permissions_minimum [0] = new RefEmitPermissionSet (
411 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
413 if (optional != null) {
414 permissions_optional = new RefEmitPermissionSet [1];
415 permissions_optional [0] = new RefEmitPermissionSet (
416 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
418 if (refused != null) {
419 permissions_refused = new RefEmitPermissionSet [1];
420 permissions_refused [0] = new RefEmitPermissionSet (
421 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
426 // Still in use by al.exe
427 internal void EmbedResourceFile (string name, string fileName)
429 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
432 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
434 if (resources != null) {
435 MonoResource[] new_r = new MonoResource [resources.Length + 1];
436 System.Array.Copy(resources, new_r, resources.Length);
439 resources = new MonoResource [1];
441 int p = resources.Length - 1;
442 resources [p].name = name;
443 resources [p].attrs = attribute;
445 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
447 resources [p].data = new byte [len];
448 s.Read (resources [p].data, 0, (int)len);
454 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
456 if (resources != null) {
457 MonoResource[] new_r = new MonoResource [resources.Length + 1];
458 System.Array.Copy(resources, new_r, resources.Length);
461 resources = new MonoResource [1];
463 int p = resources.Length - 1;
464 resources [p].name = name;
465 resources [p].attrs = attribute;
466 resources [p].data = blob;
469 internal void AddTypeForwarder (Type t) {
471 throw new ArgumentNullException ("t");
473 throw new ArgumentException ();
475 if (type_forwarders == null) {
476 type_forwarders = new Type [1] { t };
478 Type[] arr = new Type [type_forwarders.Length + 1];
479 Array.Copy (type_forwarders, arr, type_forwarders.Length);
480 arr [type_forwarders.Length] = t;
481 type_forwarders = arr;
485 public ModuleBuilder DefineDynamicModule (string name)
487 return DefineDynamicModule (name, name, false, true);
490 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
492 return DefineDynamicModule (name, name, emitSymbolInfo, true);
495 public ModuleBuilder DefineDynamicModule(string name, string fileName)
497 return DefineDynamicModule (name, fileName, false, false);
500 public ModuleBuilder DefineDynamicModule (string name, string fileName,
503 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
506 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
508 check_name_and_filename (name, fileName, false);
511 if (Path.GetExtension (fileName) == String.Empty)
512 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
514 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
516 throw new InvalidOperationException ("Assembly was already saved.");
519 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
521 if ((modules != null) && is_module_only)
522 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
524 if (modules != null) {
525 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
526 System.Array.Copy(modules, new_modules, modules.Length);
527 modules = new_modules;
529 modules = new ModuleBuilder [1];
531 modules [modules.Length - 1] = r;
535 [MethodImplAttribute(MethodImplOptions.InternalCall)]
536 private extern Module InternalAddModule (string fileName);
539 * Mono extension to support /addmodule in mcs.
541 internal Module AddModule (string fileName)
543 if (fileName == null)
544 throw new ArgumentNullException (fileName);
546 Module m = InternalAddModule (fileName);
548 if (loaded_modules != null) {
549 Module[] new_modules = new Module [loaded_modules.Length + 1];
550 System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
551 loaded_modules = new_modules;
553 loaded_modules = new Module [1];
555 loaded_modules [loaded_modules.Length - 1] = m;
560 public IResourceWriter DefineResource (string name, string description, string fileName)
562 return DefineResource (name, description, fileName, ResourceAttributes.Public);
565 public IResourceWriter DefineResource (string name, string description,
566 string fileName, ResourceAttributes attribute)
568 IResourceWriter writer;
570 // description seems to be ignored
571 AddResourceFile (name, fileName, attribute, false);
572 writer = new ResourceWriter (fileName);
573 if (resource_writers == null)
574 resource_writers = new ArrayList ();
575 resource_writers.Add (writer);
579 private void AddUnmanagedResource (Win32Resource res) {
580 MemoryStream ms = new MemoryStream ();
583 if (win32_resources != null) {
584 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
585 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
586 win32_resources = new_res;
589 win32_resources = new MonoWin32Resource [1];
591 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
594 [MonoTODO ("Not currently implemenented")]
595 public void DefineUnmanagedResource (byte[] resource)
597 if (resource == null)
598 throw new ArgumentNullException ("resource");
599 if (native_resource != NativeResourceType.None)
600 throw new ArgumentException ("Native resource has already been defined.");
602 // avoid definition of more than one unmanaged resource
603 native_resource = NativeResourceType.Unmanaged;
606 * The format of the argument byte array is not documented
607 * so this method is impossible to implement.
609 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
612 throw new NotImplementedException ();
615 public void DefineUnmanagedResource (string resourceFileName)
617 if (resourceFileName == null)
618 throw new ArgumentNullException ("resourceFileName");
619 if (resourceFileName.Length == 0)
620 throw new ArgumentException ("resourceFileName");
621 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
622 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
623 if (native_resource != NativeResourceType.None)
624 throw new ArgumentException ("Native resource has already been defined.");
626 // avoid definition of more than one unmanaged resource
627 native_resource = NativeResourceType.Unmanaged;
629 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
630 Win32ResFileReader reader = new Win32ResFileReader (fs);
632 foreach (Win32EncodedResource res in reader.ReadResources ()) {
633 if (res.Name.IsName || res.Type.IsName)
634 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
636 AddUnmanagedResource (res);
641 public void DefineVersionInfoResource ()
643 if (native_resource != NativeResourceType.None)
644 throw new ArgumentException ("Native resource has already been defined.");
646 // avoid definition of more than one unmanaged resource
647 native_resource = NativeResourceType.Assembly;
649 version_res = new Win32VersionResource (1, 0, IsCompilerContext);
652 public void DefineVersionInfoResource (string product, string productVersion,
653 string company, string copyright, string trademark)
655 if (native_resource != NativeResourceType.None)
656 throw new ArgumentException ("Native resource has already been defined.");
658 // avoid definition of more than one unmanaged resource
659 native_resource = NativeResourceType.Explicit;
662 * We can only create the resource later, when the file name and
663 * the binary version is known.
666 version_res = new Win32VersionResource (1, 0, false);
667 version_res.ProductName = product != null ? product : " ";
668 version_res.ProductVersion = productVersion != null ? productVersion : " ";
669 version_res.CompanyName = company != null ? company : " ";
670 version_res.LegalCopyright = copyright != null ? copyright : " ";
671 version_res.LegalTrademarks = trademark != null ? trademark : " ";
675 * Mono extension to support /win32icon in mcs
677 internal void DefineIconResource (string iconFileName)
679 if (iconFileName == null)
680 throw new ArgumentNullException ("iconFileName");
681 if (iconFileName.Length == 0)
682 throw new ArgumentException ("iconFileName");
683 if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
684 throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
686 using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
687 Win32IconFileReader reader = new Win32IconFileReader (fs);
689 ICONDIRENTRY[] entries = reader.ReadIcons ();
691 Win32IconResource[] icons = new Win32IconResource [entries.Length];
692 for (int i = 0; i < entries.Length; ++i) {
693 icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
694 AddUnmanagedResource (icons [i]);
697 Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
698 AddUnmanagedResource (group);
702 private void DefineVersionInfoResourceImpl (string fileName)
704 if (versioninfo_culture != null)
705 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
706 version_res.Version = version == null ? "0.0.0.0" : version;
708 if (cattrs != null) {
709 switch (native_resource) {
710 case NativeResourceType.Assembly:
711 foreach (CustomAttributeBuilder cb in cattrs) {
712 string attrname = cb.Ctor.ReflectedType.FullName;
714 if (attrname == "System.Reflection.AssemblyProductAttribute")
715 version_res.ProductName = cb.string_arg ();
716 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
717 version_res.CompanyName = cb.string_arg ();
718 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
719 version_res.LegalCopyright = cb.string_arg ();
720 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
721 version_res.LegalTrademarks = cb.string_arg ();
722 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
723 if (!IsCompilerContext)
724 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
725 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
726 string fileversion = cb.string_arg ();
727 if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
728 version_res.FileVersion = fileversion;
729 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
730 version_res.ProductVersion = cb.string_arg ();
731 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
732 version_res.FileDescription = cb.string_arg ();
733 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
734 version_res.Comments = cb.string_arg ();
737 case NativeResourceType.Explicit:
738 foreach (CustomAttributeBuilder cb in cattrs) {
739 string attrname = cb.Ctor.ReflectedType.FullName;
741 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
742 if (!IsCompilerContext)
743 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
744 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
745 version_res.Comments = cb.string_arg ();
751 version_res.OriginalFilename = fileName;
753 if (IsCompilerContext) {
754 version_res.InternalName = fileName;
755 if (version_res.ProductVersion.Trim ().Length == 0)
756 version_res.ProductVersion = version_res.FileVersion;
758 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
761 AddUnmanagedResource (version_res);
764 public ModuleBuilder GetDynamicModule (string name)
767 throw new ArgumentNullException ("name");
768 if (name.Length == 0)
769 throw new ArgumentException ("Empty name is not legal.", "name");
772 for (int i = 0; i < modules.Length; ++i)
773 if (modules [i].name == name)
778 public override Type[] GetExportedTypes ()
780 throw not_supported ();
783 public override FileStream GetFile (string name)
785 throw not_supported ();
788 public override FileStream[] GetFiles(bool getResourceModules) {
789 throw not_supported ();
792 internal override Module[] GetModulesInternal () {
794 return new Module [0];
796 return (Module[])modules.Clone ();
799 internal override Type[] GetTypes (bool exportedOnly) {
801 if (modules != null) {
802 for (int i = 0; i < modules.Length; ++i) {
803 Type[] types = modules [i].GetTypes ();
807 Type[] tmp = new Type [res.Length + types.Length];
808 Array.Copy (res, 0, tmp, 0, res.Length);
809 Array.Copy (types, 0, tmp, res.Length, types.Length);
813 if (loaded_modules != null) {
814 for (int i = 0; i < loaded_modules.Length; ++i) {
815 Type[] types = loaded_modules [i].GetTypes ();
819 Type[] tmp = new Type [res.Length + types.Length];
820 Array.Copy (res, 0, tmp, 0, res.Length);
821 Array.Copy (types, 0, tmp, res.Length, types.Length);
827 List<Exception> exceptions = null;
828 foreach (var type in res) {
829 if (type is TypeBuilder) {
830 if (exceptions == null)
831 exceptions = new List <Exception> ();
832 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
835 if (exceptions != null)
836 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
839 return res == null ? Type.EmptyTypes : res;
842 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
843 throw not_supported ();
846 public override string[] GetManifestResourceNames() {
847 throw not_supported ();
850 public override Stream GetManifestResourceStream(string name) {
851 throw not_supported ();
853 public override Stream GetManifestResourceStream(Type type, string name) {
854 throw not_supported ();
858 * This is set when the the AssemblyBuilder is created by (g)mcs
861 internal bool IsCompilerContext
863 get { return is_compiler_context; }
866 internal bool IsSave {
868 return access != (uint)AssemblyBuilderAccess.Run;
872 internal bool IsRun {
874 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
876 || access == (uint)AssemblyBuilderAccess.RunAndCollect
883 internal bool IsCollectible {
885 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
889 internal string AssemblyDir {
896 * Mono extension. If this is set, the assembly can only contain one
897 * module, access should be Save, and the saved image will not contain an
900 internal bool IsModuleOnly {
902 return is_module_only;
905 is_module_only = value;
909 ModuleBuilder manifest_module;
912 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
913 // on an assemblybuilder.
915 internal override Module GetManifestModule () {
916 if (manifest_module == null)
917 manifest_module = DefineDynamicModule ("Default Dynamic Module");
918 return manifest_module;
921 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
923 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
925 this.peKind = portableExecutableKind;
926 this.machine = imageFileMachine;
928 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
929 throw new NotImplementedException (peKind.ToString ());
930 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
931 throw new NotImplementedException (machine.ToString ());
933 if (resource_writers != null) {
934 foreach (IResourceWriter writer in resource_writers) {
940 // Create a main module if not already created
941 ModuleBuilder mainModule = null;
942 if (modules != null) {
943 foreach (ModuleBuilder module in modules)
944 if (module.FullyQualifiedName == assemblyFileName)
947 if (mainModule == null)
948 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
951 mainModule.IsMain = true;
954 * Create a new entry point if the one specified
955 * by the user is in another module.
957 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
959 if (entry_point.GetParameters ().Length == 1)
960 paramTypes = new Type [] { typeof (string) };
962 paramTypes = Type.EmptyTypes;
964 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
965 ILGenerator ilgen = mb.GetILGenerator ();
966 if (paramTypes.Length == 1)
967 ilgen.Emit (OpCodes.Ldarg_0);
968 ilgen.Emit (OpCodes.Tailcall);
969 ilgen.Emit (OpCodes.Call, entry_point);
970 ilgen.Emit (OpCodes.Ret);
975 if (version_res != null)
976 DefineVersionInfoResourceImpl (assemblyFileName);
979 // runtime needs to value to embed it into the assembly
980 public_key = sn.PublicKey;
983 foreach (ModuleBuilder module in modules)
984 if (module != mainModule)
987 // Write out the main module at the end, because it needs to
988 // contain the hash of the other modules
991 if ((sn != null) && (sn.CanSign)) {
992 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
998 public void Save (string assemblyFileName)
1000 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
1003 public void SetEntryPoint (MethodInfo entryMethod)
1005 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
1008 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
1010 if (entryMethod == null)
1011 throw new ArgumentNullException ("entryMethod");
1012 if (entryMethod.DeclaringType.Assembly != this)
1013 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
1015 entry_point = entryMethod;
1019 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
1021 if (customBuilder == null)
1022 throw new ArgumentNullException ("customBuilder");
1024 if (IsCompilerContext) {
1025 string attrname = customBuilder.Ctor.ReflectedType.FullName;
1029 if (attrname == "System.Reflection.AssemblyVersionAttribute") {
1030 version = create_assembly_version (customBuilder.string_arg ());
1032 } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
1033 culture = GetCultureString (customBuilder.string_arg ());
1034 } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
1035 data = customBuilder.Data;
1037 algid = (uint) data [pos];
1038 algid |= ((uint) data [pos + 1]) << 8;
1039 algid |= ((uint) data [pos + 2]) << 16;
1040 algid |= ((uint) data [pos + 3]) << 24;
1041 } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
1042 data = customBuilder.Data;
1044 flags |= (uint) data [pos];
1045 flags |= ((uint) data [pos + 1]) << 8;
1046 flags |= ((uint) data [pos + 2]) << 16;
1047 flags |= ((uint) data [pos + 3]) << 24;
1049 // ignore PublicKey flag if assembly is not strongnamed
1051 flags &= ~(uint) AssemblyNameFlags.PublicKey;
1055 if (cattrs != null) {
1056 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
1057 cattrs.CopyTo (new_array, 0);
1058 new_array [cattrs.Length] = customBuilder;
1061 cattrs = new CustomAttributeBuilder [1];
1062 cattrs [0] = customBuilder;
1067 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
1069 throw new ArgumentNullException ("con");
1070 if (binaryAttribute == null)
1071 throw new ArgumentNullException ("binaryAttribute");
1073 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
1076 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
1077 this.corlib_object_type = corlib_object_type;
1078 this.corlib_value_type = corlib_value_type;
1079 this.corlib_enum_type = corlib_enum_type;
1082 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
1084 SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
1085 this.corlib_void_type = corlib_void_type;
1088 private Exception not_supported () {
1089 // Strange message but this is what MS.NET prints...
1090 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
1093 private void check_name_and_filename (string name, string fileName,
1094 bool fileNeedsToExists) {
1096 throw new ArgumentNullException ("name");
1097 if (fileName == null)
1098 throw new ArgumentNullException ("fileName");
1099 if (name.Length == 0)
1100 throw new ArgumentException ("Empty name is not legal.", "name");
1101 if (fileName.Length == 0)
1102 throw new ArgumentException ("Empty file name is not legal.", "fileName");
1103 if (Path.GetFileName (fileName) != fileName)
1104 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
1106 // Resource files are created/searched under the assembly storage
1108 string fullFileName = fileName;
1110 fullFileName = Path.Combine (dir, fileName);
1112 if (fileNeedsToExists && !File.Exists (fullFileName))
1113 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
1115 if (resources != null) {
1116 for (int i = 0; i < resources.Length; ++i) {
1117 if (resources [i].filename == fullFileName)
1118 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1119 if (resources [i].name == name)
1120 throw new ArgumentException ("Duplicate name '" + name + "'");
1124 if (modules != null) {
1125 for (int i = 0; i < modules.Length; ++i) {
1126 // Use fileName instead of fullFileName here
1127 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1128 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1129 if (modules [i].Name == name)
1130 throw new ArgumentException ("Duplicate name '" + name + "'");
1135 private String create_assembly_version (String version) {
1136 String[] parts = version.Split ('.');
1137 int[] ver = new int [4] { 0, 0, 0, 0 };
1139 if ((parts.Length < 0) || (parts.Length > 4))
1140 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1142 for (int i = 0; i < parts.Length; ++i) {
1143 if (parts [i] == "*") {
1144 DateTime now = DateTime.Now;
1147 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1148 if (parts.Length == 3)
1149 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1153 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1155 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1159 ver [i] = Int32.Parse (parts [i]);
1161 catch (FormatException) {
1162 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1167 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1170 private string GetCultureString (string str)
1172 return (str == "neutral" ? String.Empty : str);
1175 internal override AssemblyName UnprotectedGetName ()
1177 AssemblyName an = base.UnprotectedGetName ();
1179 an.SetPublicKey (sn.PublicKey);
1180 an.SetPublicKeyToken (sn.PublicKeyToken);
1185 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1186 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1188 if (!IsCompilerContext)
1189 return new MonoGenericClass (gtd, typeArguments);
1191 GenericInstanceKey key = new GenericInstanceKey (gtd, typeArguments);
1192 MonoGenericClass res = (MonoGenericClass)generic_instances [key];
1194 res = new MonoGenericClass (gtd, typeArguments);
1195 generic_instances [key] = res;
1200 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1202 throw new NotImplementedException ();
1205 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1207 throw new NotImplementedException ();
1210 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1212 throw new NotImplementedException ();
1215 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1217 throw new NotImplementedException ();
1220 #if NET_4_0 || MOONLIGHT || MOBILE
1221 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1224 throw new ArgumentNullException (name);
1225 if (name.Length == 0)
1226 throw new ArgumentException ("name", "Name cannot be empty");
1228 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1229 if (res is TypeBuilder) {
1231 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1237 public override Module GetModule (String name)
1240 throw new ArgumentNullException ("name");
1241 if (name.Length == 0)
1242 throw new ArgumentException ("Name can't be empty");
1244 if (modules == null)
1247 foreach (Module module in modules) {
1248 if (module.ScopeName == name)
1255 public override Module[] GetModules (bool getResourceModules)
1257 Module[] modules = GetModulesInternal ();
1259 if (!getResourceModules) {
1260 var result = new List<Module> (modules.Length);
1261 foreach (Module m in modules)
1262 if (!m.IsResource ())
1264 return result.ToArray ();
1269 [MonoTODO ("This always returns an empty array")]
1270 public override AssemblyName[] GetReferencedAssemblies () {
1271 return GetReferencedAssemblies (this);
1274 public override Module[] GetLoadedModules (bool getResourceModules)
1276 return GetModules (getResourceModules);
1279 //FIXME MS has issues loading satelite assemblies from SRE
1280 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1282 return GetSatelliteAssembly (culture, null, true);
1285 //FIXME MS has issues loading satelite assemblies from SRE
1286 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1288 return GetSatelliteAssembly (culture, version, true);
1291 public override Module ManifestModule {
1293 return GetManifestModule ();
1297 public override bool GlobalAssemblyCache {
1303 public override bool IsDynamic {
1304 get { return true; }