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.Runtime.InteropServices;
43 using System.Security;
44 using System.Security.Cryptography;
45 using System.Security.Permissions;
48 using Mono.Security.Cryptography;
50 namespace System.Reflection.Emit
52 internal enum NativeResourceType
60 internal struct RefEmitPermissionSet {
61 public SecurityAction action;
64 public RefEmitPermissionSet (SecurityAction action, string pset) {
70 internal struct MonoResource {
73 public string filename;
74 public ResourceAttributes attrs;
79 internal struct MonoWin32Resource {
85 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
86 this.res_type = res_type;
88 this.lang_id = lang_id;
93 internal class GenericInstanceKey {
98 internal GenericInstanceKey (Type gtd, Type[] args)
103 hash_code = gtd.GetHashCode ();
104 for (int i = 0; i < args.Length; ++i)
105 hash_code ^= args [i].GetHashCode ();
108 static bool IsBoundedVector (Type type) {
109 ArrayType at = type as ArrayType;
111 return at.GetEffectiveRank () == 1;
112 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
115 static bool TypeEquals (Type a, Type b) {
119 if (a.HasElementType) {
120 if (!b.HasElementType)
122 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
127 int rank = a.GetArrayRank ();
128 if (rank != b.GetArrayRank ())
130 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
132 } else if (a.IsByRef) {
135 } else if (a.IsPointer) {
142 if (a.IsGenericType) {
143 if (!b.IsGenericType)
145 if (a.IsGenericParameter)
147 if (a.IsGenericParameter) //previous test should have caught it
150 if (a.IsGenericTypeDefinition) {
151 if (!b.IsGenericTypeDefinition)
154 if (b.IsGenericTypeDefinition)
156 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
159 Type[] argsA = a.GetGenericArguments ();
160 Type[] argsB = b.GetGenericArguments ();
161 for (int i = 0; i < argsA.Length; ++i) {
162 if (!TypeEquals (argsA [i], argsB [i]))
169 Now only non-generic, non compound types are left. To properly deal with user
170 types we would have to call UnderlyingSystemType, but we let them have their
171 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
172 depend on proper UT canonicalization.
177 public override bool Equals (object obj)
179 GenericInstanceKey other = obj as GenericInstanceKey;
182 if (gtd != other.gtd)
184 for (int i = 0; i < args.Length; ++i) {
186 Type b = other.args [i];
188 We must cannonicalize as much as we can. Using equals means that some resulting types
189 won't have the exact same types as the argument ones.
190 For example, flyweight types used array, pointer and byref will should this behavior.
191 MCS seens to be resilient to this problem so hopefully this won't show up.
193 if (a != b && !a.Equals (b))
199 public override int GetHashCode ()
207 [ComDefaultInterface (typeof (_AssemblyBuilder))]
208 [ClassInterface (ClassInterfaceType.None)]
209 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
210 #pragma warning disable 169, 414
211 #region Sync with object-internals.h
212 private UIntPtr dynamic_assembly; /* GC-tracked */
213 private MethodInfo entry_point;
214 private ModuleBuilder[] modules;
217 private CustomAttributeBuilder[] cattrs;
218 private MonoResource[] resources;
224 PEFileKinds pekind = PEFileKinds.Dll;
227 Module[] loaded_modules;
228 MonoWin32Resource[] win32_resources;
229 private RefEmitPermissionSet[] permissions_minimum;
230 private RefEmitPermissionSet[] permissions_optional;
231 private RefEmitPermissionSet[] permissions_refused;
232 PortableExecutableKinds peKind;
233 ImageFileMachine machine;
234 bool corlib_internal;
235 Type[] type_forwarders;
238 #pragma warning restore 169, 414
240 internal Type corlib_object_type = typeof (System.Object);
241 internal Type corlib_value_type = typeof (System.ValueType);
242 internal Type corlib_enum_type = typeof (System.Enum);
243 internal Type corlib_void_type = typeof (void);
244 ArrayList resource_writers = null;
245 Win32VersionResource version_res;
248 private Mono.Security.StrongName sn;
249 NativeResourceType native_resource;
250 readonly bool is_compiler_context;
251 string versioninfo_culture;
252 Hashtable generic_instances = new Hashtable ();
254 [MethodImplAttribute(MethodImplOptions.InternalCall)]
255 private static extern void basic_init (AssemblyBuilder ab);
257 /* Keep this in sync with codegen.cs in mcs */
258 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
260 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
262 is_compiler_context = (access & COMPILER_ACCESS) != 0;
264 // remove Mono specific flag to allow enum check to pass
265 access &= ~COMPILER_ACCESS;
268 // only "Run" is supported by Silverlight
269 // however SMCS requires more than this but runs outside the CoreCLR sandbox
270 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
271 throw new ArgumentException ("access");
274 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
275 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
276 "Argument value {0} is not valid.", (int) access),
280 if ((access & AssemblyBuilderAccess.RunAndCollect) == AssemblyBuilderAccess.RunAndCollect)
281 throw new NotSupportedException ("RunAndCollect not yet supported.");
285 this.access = (uint)access;
286 flags = (uint) n.Flags;
288 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
289 if (IsSave && (directory == null || directory.Length == 0)) {
290 dir = Directory.GetCurrentDirectory ();
295 /* Set defaults from n */
296 if (n.CultureInfo != null) {
297 culture = n.CultureInfo.Name;
298 versioninfo_culture = n.CultureInfo.Name;
300 Version v = n.Version;
302 version = v.ToString ();
305 if (n.KeyPair != null) {
306 // full keypair is available (for signing)
307 sn = n.KeyPair.StrongName ();
309 // public key is available (for delay-signing)
310 byte[] pk = n.GetPublicKey ();
311 if ((pk != null) && (pk.Length > 0)) {
312 sn = new Mono.Security.StrongName (pk);
317 flags |= (uint) AssemblyNameFlags.PublicKey;
319 this.corlib_internal = corlib_internal;
321 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
323 foreach (byte pkb in sn.PublicKeyToken) {
324 string part = pkb.ToString("x2");
325 this.pktoken[pkti++] = (byte)part[0];
326 this.pktoken[pkti++] = (byte)part[1];
333 public override string CodeBase {
335 throw not_supported ();
339 public override MethodInfo EntryPoint {
345 public override string Location {
347 throw not_supported ();
351 /* This is to keep signature compatibility with MS.NET */
352 public override string ImageRuntimeVersion {
354 return base.ImageRuntimeVersion;
359 public override bool ReflectionOnly {
360 get { return base.ReflectionOnly; }
363 public void AddResourceFile (string name, string fileName)
365 AddResourceFile (name, fileName, ResourceAttributes.Public);
368 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
370 AddResourceFile (name, fileName, attribute, true);
373 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
375 check_name_and_filename (name, fileName, fileNeedsToExists);
377 // Resource files are created/searched under the assembly storage
380 fileName = Path.Combine (dir, fileName);
382 if (resources != null) {
383 MonoResource[] new_r = new MonoResource [resources.Length + 1];
384 System.Array.Copy(resources, new_r, resources.Length);
387 resources = new MonoResource [1];
389 int p = resources.Length - 1;
390 resources [p].name = name;
391 resources [p].filename = fileName;
392 resources [p].attrs = attribute;
396 /// Don't change the method name and parameters order. It is used by mcs
398 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
402 throw new InvalidOperationException ("Assembly was already saved.");
404 // required for base Assembly class (so the permissions
405 // can be used even if the assembly isn't saved to disk)
407 _optional = optional;
410 // required to reuse AddDeclarativeSecurity support
411 // already present in the runtime
412 if (required != null) {
413 permissions_minimum = new RefEmitPermissionSet [1];
414 permissions_minimum [0] = new RefEmitPermissionSet (
415 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
417 if (optional != null) {
418 permissions_optional = new RefEmitPermissionSet [1];
419 permissions_optional [0] = new RefEmitPermissionSet (
420 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
422 if (refused != null) {
423 permissions_refused = new RefEmitPermissionSet [1];
424 permissions_refused [0] = new RefEmitPermissionSet (
425 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
430 internal void EmbedResourceFile (string name, string fileName)
432 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
435 internal void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
437 if (resources != null) {
438 MonoResource[] new_r = new MonoResource [resources.Length + 1];
439 System.Array.Copy(resources, new_r, resources.Length);
442 resources = new MonoResource [1];
444 int p = resources.Length - 1;
445 resources [p].name = name;
446 resources [p].attrs = attribute;
448 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
450 resources [p].data = new byte [len];
451 s.Read (resources [p].data, 0, (int)len);
458 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
460 if (resources != null) {
461 MonoResource[] new_r = new MonoResource [resources.Length + 1];
462 System.Array.Copy(resources, new_r, resources.Length);
465 resources = new MonoResource [1];
467 int p = resources.Length - 1;
468 resources [p].name = name;
469 resources [p].attrs = attribute;
470 resources [p].data = blob;
473 internal void AddTypeForwarder (Type t) {
475 throw new ArgumentNullException ("t");
477 throw new ArgumentException ();
479 if (type_forwarders == null) {
480 type_forwarders = new Type [1] { t };
482 Type[] arr = new Type [type_forwarders.Length + 1];
483 Array.Copy (type_forwarders, arr, type_forwarders.Length);
484 arr [type_forwarders.Length] = t;
485 type_forwarders = arr;
489 public ModuleBuilder DefineDynamicModule (string name)
491 return DefineDynamicModule (name, name, false, true);
494 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
496 return DefineDynamicModule (name, name, emitSymbolInfo, true);
499 public ModuleBuilder DefineDynamicModule(string name, string fileName)
501 return DefineDynamicModule (name, fileName, false, false);
504 public ModuleBuilder DefineDynamicModule (string name, string fileName,
507 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
510 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
512 check_name_and_filename (name, fileName, false);
515 if (Path.GetExtension (fileName) == String.Empty)
516 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
518 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
520 throw new InvalidOperationException ("Assembly was already saved.");
523 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
525 if ((modules != null) && is_module_only)
526 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
528 if (modules != null) {
529 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
530 System.Array.Copy(modules, new_modules, modules.Length);
531 modules = new_modules;
533 modules = new ModuleBuilder [1];
535 modules [modules.Length - 1] = r;
539 [MethodImplAttribute(MethodImplOptions.InternalCall)]
540 private extern Module InternalAddModule (string fileName);
543 * Mono extension to support /addmodule in mcs.
545 internal Module AddModule (string fileName)
547 if (fileName == null)
548 throw new ArgumentNullException (fileName);
550 Module m = InternalAddModule (fileName);
552 if (loaded_modules != null) {
553 Module[] new_modules = new Module [loaded_modules.Length + 1];
554 System.Array.Copy (loaded_modules, new_modules, loaded_modules.Length);
555 loaded_modules = new_modules;
557 loaded_modules = new Module [1];
559 loaded_modules [loaded_modules.Length - 1] = m;
564 public IResourceWriter DefineResource (string name, string description, string fileName)
566 return DefineResource (name, description, fileName, ResourceAttributes.Public);
569 public IResourceWriter DefineResource (string name, string description,
570 string fileName, ResourceAttributes attribute)
572 IResourceWriter writer;
574 // description seems to be ignored
575 AddResourceFile (name, fileName, attribute, false);
576 writer = new ResourceWriter (fileName);
577 if (resource_writers == null)
578 resource_writers = new ArrayList ();
579 resource_writers.Add (writer);
583 private void AddUnmanagedResource (Win32Resource res) {
584 MemoryStream ms = new MemoryStream ();
587 if (win32_resources != null) {
588 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
589 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
590 win32_resources = new_res;
593 win32_resources = new MonoWin32Resource [1];
595 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
598 [MonoTODO ("Not currently implemenented")]
599 public void DefineUnmanagedResource (byte[] resource)
601 if (resource == null)
602 throw new ArgumentNullException ("resource");
603 if (native_resource != NativeResourceType.None)
604 throw new ArgumentException ("Native resource has already been defined.");
606 // avoid definition of more than one unmanaged resource
607 native_resource = NativeResourceType.Unmanaged;
610 * The format of the argument byte array is not documented
611 * so this method is impossible to implement.
614 throw new NotImplementedException ();
617 public void DefineUnmanagedResource (string resourceFileName)
619 if (resourceFileName == null)
620 throw new ArgumentNullException ("resourceFileName");
621 if (resourceFileName.Length == 0)
622 throw new ArgumentException ("resourceFileName");
623 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
624 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
625 if (native_resource != NativeResourceType.None)
626 throw new ArgumentException ("Native resource has already been defined.");
628 // avoid definition of more than one unmanaged resource
629 native_resource = NativeResourceType.Unmanaged;
631 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
632 Win32ResFileReader reader = new Win32ResFileReader (fs);
634 foreach (Win32EncodedResource res in reader.ReadResources ()) {
635 if (res.Name.IsName || res.Type.IsName)
636 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
638 AddUnmanagedResource (res);
643 public void DefineVersionInfoResource ()
645 if (native_resource != NativeResourceType.None)
646 throw new ArgumentException ("Native resource has already been defined.");
648 // avoid definition of more than one unmanaged resource
649 native_resource = NativeResourceType.Assembly;
651 version_res = new Win32VersionResource (1, 0, IsCompilerContext);
654 public void DefineVersionInfoResource (string product, string productVersion,
655 string company, string copyright, string trademark)
657 if (native_resource != NativeResourceType.None)
658 throw new ArgumentException ("Native resource has already been defined.");
660 // avoid definition of more than one unmanaged resource
661 native_resource = NativeResourceType.Explicit;
664 * We can only create the resource later, when the file name and
665 * the binary version is known.
668 version_res = new Win32VersionResource (1, 0, false);
669 version_res.ProductName = product != null ? product : " ";
670 version_res.ProductVersion = productVersion != null ? productVersion : " ";
671 version_res.CompanyName = company != null ? company : " ";
672 version_res.LegalCopyright = copyright != null ? copyright : " ";
673 version_res.LegalTrademarks = trademark != null ? trademark : " ";
677 * Mono extension to support /win32icon in mcs
679 internal void DefineIconResource (string iconFileName)
681 if (iconFileName == null)
682 throw new ArgumentNullException ("iconFileName");
683 if (iconFileName.Length == 0)
684 throw new ArgumentException ("iconFileName");
685 if (!File.Exists (iconFileName) || Directory.Exists (iconFileName))
686 throw new FileNotFoundException ("File '" + iconFileName + "' does not exists or is a directory.");
688 using (FileStream fs = new FileStream (iconFileName, FileMode.Open, FileAccess.Read)) {
689 Win32IconFileReader reader = new Win32IconFileReader (fs);
691 ICONDIRENTRY[] entries = reader.ReadIcons ();
693 Win32IconResource[] icons = new Win32IconResource [entries.Length];
694 for (int i = 0; i < entries.Length; ++i) {
695 icons [i] = new Win32IconResource (i + 1, 0, entries [i]);
696 AddUnmanagedResource (icons [i]);
699 Win32GroupIconResource group = new Win32GroupIconResource (1, 0, icons);
700 AddUnmanagedResource (group);
704 private void DefineVersionInfoResourceImpl (string fileName)
706 if (versioninfo_culture != null)
707 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
708 version_res.Version = version == null ? "0.0.0.0" : version;
710 if (cattrs != null) {
711 switch (native_resource) {
712 case NativeResourceType.Assembly:
713 foreach (CustomAttributeBuilder cb in cattrs) {
714 string attrname = cb.Ctor.ReflectedType.FullName;
716 if (attrname == "System.Reflection.AssemblyProductAttribute")
717 version_res.ProductName = cb.string_arg ();
718 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
719 version_res.CompanyName = cb.string_arg ();
720 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
721 version_res.LegalCopyright = cb.string_arg ();
722 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
723 version_res.LegalTrademarks = cb.string_arg ();
724 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
725 if (!IsCompilerContext)
726 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
727 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
728 string fileversion = cb.string_arg ();
729 if (!IsCompilerContext || fileversion != null && fileversion.Length != 0)
730 version_res.FileVersion = fileversion;
731 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
732 version_res.ProductVersion = cb.string_arg ();
733 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
734 version_res.FileDescription = cb.string_arg ();
735 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
736 version_res.Comments = cb.string_arg ();
739 case NativeResourceType.Explicit:
740 foreach (CustomAttributeBuilder cb in cattrs) {
741 string attrname = cb.Ctor.ReflectedType.FullName;
743 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
744 if (!IsCompilerContext)
745 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
746 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
747 version_res.Comments = cb.string_arg ();
753 version_res.OriginalFilename = fileName;
755 if (IsCompilerContext) {
756 version_res.InternalName = fileName;
757 if (version_res.ProductVersion.Trim ().Length == 0)
758 version_res.ProductVersion = version_res.FileVersion;
760 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
763 AddUnmanagedResource (version_res);
766 public ModuleBuilder GetDynamicModule (string name)
769 throw new ArgumentNullException ("name");
770 if (name.Length == 0)
771 throw new ArgumentException ("Empty name is not legal.", "name");
774 for (int i = 0; i < modules.Length; ++i)
775 if (modules [i].name == name)
780 public override Type[] GetExportedTypes ()
782 throw not_supported ();
785 public override FileStream GetFile (string name)
787 throw not_supported ();
790 public override FileStream[] GetFiles(bool getResourceModules) {
791 throw not_supported ();
794 internal override Module[] GetModulesInternal () {
796 return new Module [0];
798 return (Module[])modules.Clone ();
801 internal override Type[] GetTypes (bool exportedOnly) {
803 if (modules != null) {
804 for (int i = 0; i < modules.Length; ++i) {
805 Type[] types = modules [i].GetTypes ();
809 Type[] tmp = new Type [res.Length + types.Length];
810 Array.Copy (res, 0, tmp, 0, res.Length);
811 Array.Copy (types, 0, tmp, res.Length, types.Length);
815 if (loaded_modules != null) {
816 for (int i = 0; i < loaded_modules.Length; ++i) {
817 Type[] types = loaded_modules [i].GetTypes ();
821 Type[] tmp = new Type [res.Length + types.Length];
822 Array.Copy (res, 0, tmp, 0, res.Length);
823 Array.Copy (types, 0, tmp, res.Length, types.Length);
828 return res == null ? Type.EmptyTypes : res;
831 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
832 throw not_supported ();
835 public override string[] GetManifestResourceNames() {
836 throw not_supported ();
839 public override Stream GetManifestResourceStream(string name) {
840 throw not_supported ();
842 public override Stream GetManifestResourceStream(Type type, string name) {
843 throw not_supported ();
847 * This is set when the the AssemblyBuilder is created by (g)mcs
850 internal bool IsCompilerContext
852 get { return is_compiler_context; }
855 internal bool IsSave {
857 return access != (uint)AssemblyBuilderAccess.Run;
861 internal bool IsRun {
863 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
865 || access == (uint)AssemblyBuilderAccess.RunAndCollect
872 internal string AssemblyDir {
879 * Mono extension. If this is set, the assembly can only contain one
880 * module, access should be Save, and the saved image will not contain an
883 internal bool IsModuleOnly {
885 return is_module_only;
888 is_module_only = value;
892 ModuleBuilder manifest_module;
895 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
896 // on an assemblybuilder.
898 internal override Module GetManifestModule () {
899 if (manifest_module == null)
900 manifest_module = DefineDynamicModule ("Default Dynamic Module");
901 return manifest_module;
904 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
906 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
908 this.peKind = portableExecutableKind;
909 this.machine = imageFileMachine;
911 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
912 throw new NotImplementedException (peKind.ToString ());
913 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
914 throw new NotImplementedException (machine.ToString ());
916 if (resource_writers != null) {
917 foreach (IResourceWriter writer in resource_writers) {
923 // Create a main module if not already created
924 ModuleBuilder mainModule = null;
925 if (modules != null) {
926 foreach (ModuleBuilder module in modules)
927 if (module.FullyQualifiedName == assemblyFileName)
930 if (mainModule == null)
931 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
934 mainModule.IsMain = true;
937 * Create a new entry point if the one specified
938 * by the user is in another module.
940 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
942 if (entry_point.GetParameters ().Length == 1)
943 paramTypes = new Type [] { typeof (string) };
945 paramTypes = Type.EmptyTypes;
947 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
948 ILGenerator ilgen = mb.GetILGenerator ();
949 if (paramTypes.Length == 1)
950 ilgen.Emit (OpCodes.Ldarg_0);
951 ilgen.Emit (OpCodes.Tailcall);
952 ilgen.Emit (OpCodes.Call, entry_point);
953 ilgen.Emit (OpCodes.Ret);
958 if (version_res != null)
959 DefineVersionInfoResourceImpl (assemblyFileName);
962 // runtime needs to value to embed it into the assembly
963 public_key = sn.PublicKey;
966 foreach (ModuleBuilder module in modules)
967 if (module != mainModule)
970 // Write out the main module at the end, because it needs to
971 // contain the hash of the other modules
974 if ((sn != null) && (sn.CanSign)) {
975 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
981 public void Save (string assemblyFileName)
983 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
986 public void SetEntryPoint (MethodInfo entryMethod)
988 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
991 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
993 if (entryMethod == null)
994 throw new ArgumentNullException ("entryMethod");
995 if (entryMethod.DeclaringType.Assembly != this)
996 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
998 entry_point = entryMethod;
1002 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
1004 if (customBuilder == null)
1005 throw new ArgumentNullException ("customBuilder");
1007 if (IsCompilerContext) {
1008 string attrname = customBuilder.Ctor.ReflectedType.FullName;
1012 if (attrname == "System.Reflection.AssemblyVersionAttribute") {
1013 version = create_assembly_version (customBuilder.string_arg ());
1015 } else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
1016 culture = GetCultureString (customBuilder.string_arg ());
1017 } else if (attrname == "System.Reflection.AssemblyAlgorithmIdAttribute") {
1018 data = customBuilder.Data;
1020 algid = (uint) data [pos];
1021 algid |= ((uint) data [pos + 1]) << 8;
1022 algid |= ((uint) data [pos + 2]) << 16;
1023 algid |= ((uint) data [pos + 3]) << 24;
1024 } else if (attrname == "System.Reflection.AssemblyFlagsAttribute") {
1025 data = customBuilder.Data;
1027 flags |= (uint) data [pos];
1028 flags |= ((uint) data [pos + 1]) << 8;
1029 flags |= ((uint) data [pos + 2]) << 16;
1030 flags |= ((uint) data [pos + 3]) << 24;
1032 // ignore PublicKey flag if assembly is not strongnamed
1034 flags &= ~(uint) AssemblyNameFlags.PublicKey;
1038 if (cattrs != null) {
1039 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
1040 cattrs.CopyTo (new_array, 0);
1041 new_array [cattrs.Length] = customBuilder;
1044 cattrs = new CustomAttributeBuilder [1];
1045 cattrs [0] = customBuilder;
1050 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
1052 throw new ArgumentNullException ("con");
1053 if (binaryAttribute == null)
1054 throw new ArgumentNullException ("binaryAttribute");
1056 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
1059 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type) {
1060 this.corlib_object_type = corlib_object_type;
1061 this.corlib_value_type = corlib_value_type;
1062 this.corlib_enum_type = corlib_enum_type;
1065 internal void SetCorlibTypeBuilders (Type corlib_object_type, Type corlib_value_type, Type corlib_enum_type, Type corlib_void_type)
1067 SetCorlibTypeBuilders (corlib_object_type, corlib_value_type, corlib_enum_type);
1068 this.corlib_void_type = corlib_void_type;
1071 private Exception not_supported () {
1072 // Strange message but this is what MS.NET prints...
1073 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
1076 private void check_name_and_filename (string name, string fileName,
1077 bool fileNeedsToExists) {
1079 throw new ArgumentNullException ("name");
1080 if (fileName == null)
1081 throw new ArgumentNullException ("fileName");
1082 if (name.Length == 0)
1083 throw new ArgumentException ("Empty name is not legal.", "name");
1084 if (fileName.Length == 0)
1085 throw new ArgumentException ("Empty file name is not legal.", "fileName");
1086 if (Path.GetFileName (fileName) != fileName)
1087 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
1089 // Resource files are created/searched under the assembly storage
1091 string fullFileName = fileName;
1093 fullFileName = Path.Combine (dir, fileName);
1095 if (fileNeedsToExists && !File.Exists (fullFileName))
1096 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
1098 if (resources != null) {
1099 for (int i = 0; i < resources.Length; ++i) {
1100 if (resources [i].filename == fullFileName)
1101 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1102 if (resources [i].name == name)
1103 throw new ArgumentException ("Duplicate name '" + name + "'");
1107 if (modules != null) {
1108 for (int i = 0; i < modules.Length; ++i) {
1109 // Use fileName instead of fullFileName here
1110 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1111 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1112 if (modules [i].Name == name)
1113 throw new ArgumentException ("Duplicate name '" + name + "'");
1118 private String create_assembly_version (String version) {
1119 String[] parts = version.Split ('.');
1120 int[] ver = new int [4] { 0, 0, 0, 0 };
1122 if ((parts.Length < 0) || (parts.Length > 4))
1123 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1125 for (int i = 0; i < parts.Length; ++i) {
1126 if (parts [i] == "*") {
1127 DateTime now = DateTime.Now;
1130 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1131 if (parts.Length == 3)
1132 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1136 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1138 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1142 ver [i] = Int32.Parse (parts [i]);
1144 catch (FormatException) {
1145 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1150 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1153 private string GetCultureString (string str)
1155 return (str == "neutral" ? String.Empty : str);
1158 internal override AssemblyName UnprotectedGetName ()
1160 AssemblyName an = base.UnprotectedGetName ();
1162 an.SetPublicKey (sn.PublicKey);
1163 an.SetPublicKeyToken (sn.PublicKeyToken);
1168 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1169 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1171 if (!IsCompilerContext)
1172 return new MonoGenericClass (gtd, typeArguments);
1174 GenericInstanceKey key = new GenericInstanceKey (gtd, typeArguments);
1175 MonoGenericClass res = (MonoGenericClass)generic_instances [key];
1177 res = new MonoGenericClass (gtd, typeArguments);
1178 generic_instances [key] = res;
1183 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1185 throw new NotImplementedException ();
1188 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1190 throw new NotImplementedException ();
1193 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1195 throw new NotImplementedException ();
1198 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1200 throw new NotImplementedException ();
1204 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1207 throw new ArgumentNullException (name);
1208 if (name.Length == 0)
1209 throw new ArgumentException ("name", "Name cannot be empty");
1211 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1212 if (res is TypeBuilder) {
1214 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1220 public override Module GetModule (String name)
1223 throw new ArgumentNullException ("name");
1224 if (name.Length == 0)
1225 throw new ArgumentException ("Name can't be empty");
1227 if (modules == null)
1230 foreach (Module module in modules) {
1231 if (module.ScopeName == name)
1238 public override Module[] GetModules (bool getResourceModules)
1240 Module[] modules = GetModulesInternal ();
1242 if (!getResourceModules) {
1243 ArrayList result = new ArrayList (modules.Length);
1244 foreach (Module m in modules)
1245 if (!m.IsResource ())
1247 return (Module[])result.ToArray (typeof (Module));
1252 [MonoTODO ("This always returns an empty array")]
1253 public override AssemblyName[] GetReferencedAssemblies () {
1254 return GetReferencedAssemblies (this);
1257 public override Module[] GetLoadedModules (bool getResourceModules)
1259 return GetModules (getResourceModules);
1262 //FIXME MS has issues loading satelite assemblies from SRE
1263 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1265 return GetSatelliteAssembly (culture, null, true);
1268 //FIXME MS has issues loading satelite assemblies from SRE
1269 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1271 return GetSatelliteAssembly (culture, version, true);
1274 public override Module ManifestModule {
1276 return GetManifestModule ();
1280 public override bool GlobalAssemblyCache {
1286 public override bool IsDynamic {
1287 get { return true; }