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.
35 using System.Reflection;
36 using System.Resources;
38 using System.Security.Policy;
39 using System.Runtime.Serialization;
40 using System.Globalization;
41 using System.Runtime.CompilerServices;
42 using System.Collections;
43 using System.Collections.Generic;
44 using System.Runtime.InteropServices;
45 using System.Security;
46 using System.Security.Cryptography;
47 using System.Security.Permissions;
50 using Mono.Security.Cryptography;
52 namespace System.Reflection.Emit
54 internal enum NativeResourceType
62 internal struct RefEmitPermissionSet {
63 public SecurityAction action;
66 public RefEmitPermissionSet (SecurityAction action, string pset) {
72 internal struct MonoResource {
73 #pragma warning disable 649
76 public string filename;
77 public ResourceAttributes attrs;
80 #pragma warning restore 649
83 internal struct MonoWin32Resource {
89 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
90 this.res_type = res_type;
92 this.lang_id = lang_id;
97 internal class GenericInstanceKey {
102 internal GenericInstanceKey (Type gtd, Type[] args)
107 hash_code = gtd.GetHashCode ();
108 for (int i = 0; i < args.Length; ++i)
109 hash_code ^= args [i].GetHashCode ();
112 static bool IsBoundedVector (Type type) {
113 ArrayType at = type as ArrayType;
115 return at.GetEffectiveRank () == 1;
116 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
119 static bool TypeEquals (Type a, Type b) {
123 if (a.HasElementType) {
124 if (!b.HasElementType)
126 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
131 int rank = a.GetArrayRank ();
132 if (rank != b.GetArrayRank ())
134 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
136 } else if (a.IsByRef) {
139 } else if (a.IsPointer) {
146 if (a.IsGenericType) {
147 if (!b.IsGenericType)
149 if (a.IsGenericParameter)
151 if (a.IsGenericParameter) //previous test should have caught it
154 if (a.IsGenericTypeDefinition) {
155 if (!b.IsGenericTypeDefinition)
158 if (b.IsGenericTypeDefinition)
160 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
163 Type[] argsA = a.GetGenericArguments ();
164 Type[] argsB = b.GetGenericArguments ();
165 for (int i = 0; i < argsA.Length; ++i) {
166 if (!TypeEquals (argsA [i], argsB [i]))
173 Now only non-generic, non compound types are left. To properly deal with user
174 types we would have to call UnderlyingSystemType, but we let them have their
175 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
176 depend on proper UT canonicalization.
181 public override bool Equals (object obj)
183 GenericInstanceKey other = obj as GenericInstanceKey;
186 if (gtd != other.gtd)
188 for (int i = 0; i < args.Length; ++i) {
190 Type b = other.args [i];
192 We must cannonicalize as much as we can. Using equals means that some resulting types
193 won't have the exact same types as the argument ones.
194 For example, flyweight types used array, pointer and byref will should this behavior.
195 MCS seens to be resilient to this problem so hopefully this won't show up.
197 if (a != b && !a.Equals (b))
203 public override int GetHashCode ()
211 [ComDefaultInterface (typeof (_AssemblyBuilder))]
212 [ClassInterface (ClassInterfaceType.None)]
213 [StructLayout (LayoutKind.Sequential)]
214 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
215 #pragma warning disable 169, 414, 649
216 #region Sync with object-internals.h
217 private UIntPtr dynamic_assembly; /* GC-tracked */
218 private MethodInfo entry_point;
219 private ModuleBuilder[] modules;
222 private CustomAttributeBuilder[] cattrs;
223 private MonoResource[] resources;
229 PEFileKinds pekind = PEFileKinds.Dll;
232 Module[] loaded_modules;
233 MonoWin32Resource[] win32_resources;
234 private RefEmitPermissionSet[] permissions_minimum;
235 private RefEmitPermissionSet[] permissions_optional;
236 private RefEmitPermissionSet[] permissions_refused;
237 PortableExecutableKinds peKind;
238 ImageFileMachine machine;
239 bool corlib_internal;
240 Type[] type_forwarders;
243 #pragma warning restore 169, 414, 649
245 internal Type corlib_object_type = typeof (System.Object);
246 internal Type corlib_value_type = typeof (System.ValueType);
247 internal Type corlib_enum_type = typeof (System.Enum);
248 internal Type corlib_void_type = typeof (void);
249 ArrayList resource_writers = null;
250 Win32VersionResource version_res;
253 private Mono.Security.StrongName sn;
254 NativeResourceType native_resource;
255 string versioninfo_culture;
257 [MethodImplAttribute(MethodImplOptions.InternalCall)]
258 private static extern void basic_init (AssemblyBuilder ab);
260 /* Keep this in sync with codegen.cs in mcs */
261 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
263 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
265 /* This is obsolete now, as mcs doesn't use SRE any more */
266 if ((access & COMPILER_ACCESS) != 0)
267 throw new NotImplementedException ("COMPILER_ACCESS is no longer supperted, use a newer mcs.");
269 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
270 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
271 "Argument value {0} is not valid.", (int) access),
275 this.access = (uint)access;
276 flags = (uint) n.Flags;
278 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
279 if (IsSave && (directory == null || directory.Length == 0)) {
280 dir = Directory.GetCurrentDirectory ();
285 /* Set defaults from n */
286 if (n.CultureInfo != null) {
287 culture = n.CultureInfo.Name;
288 versioninfo_culture = n.CultureInfo.Name;
290 Version v = n.Version;
292 version = v.ToString ();
295 if (n.KeyPair != null) {
296 // full keypair is available (for signing)
297 sn = n.KeyPair.StrongName ();
299 // public key is available (for delay-signing)
300 byte[] pk = n.GetPublicKey ();
301 if ((pk != null) && (pk.Length > 0)) {
302 sn = new Mono.Security.StrongName (pk);
307 flags |= (uint) AssemblyNameFlags.PublicKey;
309 this.corlib_internal = corlib_internal;
311 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
313 foreach (byte pkb in sn.PublicKeyToken) {
314 string part = pkb.ToString("x2");
315 this.pktoken[pkti++] = (byte)part[0];
316 this.pktoken[pkti++] = (byte)part[1];
323 public override string CodeBase {
325 throw not_supported ();
329 public override MethodInfo EntryPoint {
335 public override string Location {
337 throw not_supported ();
341 /* This is to keep signature compatibility with MS.NET */
342 public override string ImageRuntimeVersion {
344 return base.ImageRuntimeVersion;
349 public override bool ReflectionOnly {
350 get { return base.ReflectionOnly; }
353 public void AddResourceFile (string name, string fileName)
355 AddResourceFile (name, fileName, ResourceAttributes.Public);
358 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
360 AddResourceFile (name, fileName, attribute, true);
363 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
365 check_name_and_filename (name, fileName, fileNeedsToExists);
367 // Resource files are created/searched under the assembly storage
370 fileName = Path.Combine (dir, fileName);
372 if (resources != null) {
373 MonoResource[] new_r = new MonoResource [resources.Length + 1];
374 System.Array.Copy(resources, new_r, resources.Length);
377 resources = new MonoResource [1];
379 int p = resources.Length - 1;
380 resources [p].name = name;
381 resources [p].filename = fileName;
382 resources [p].attrs = attribute;
385 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
389 throw new InvalidOperationException ("Assembly was already saved.");
391 // required for base Assembly class (so the permissions
392 // can be used even if the assembly isn't saved to disk)
394 _optional = optional;
397 // required to reuse AddDeclarativeSecurity support
398 // already present in the runtime
399 if (required != null) {
400 permissions_minimum = new RefEmitPermissionSet [1];
401 permissions_minimum [0] = new RefEmitPermissionSet (
402 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
404 if (optional != null) {
405 permissions_optional = new RefEmitPermissionSet [1];
406 permissions_optional [0] = new RefEmitPermissionSet (
407 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
409 if (refused != null) {
410 permissions_refused = new RefEmitPermissionSet [1];
411 permissions_refused [0] = new RefEmitPermissionSet (
412 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
417 // Still in use by al.exe
418 internal void EmbedResourceFile (string name, string fileName)
420 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
423 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
425 if (resources != null) {
426 MonoResource[] new_r = new MonoResource [resources.Length + 1];
427 System.Array.Copy(resources, new_r, resources.Length);
430 resources = new MonoResource [1];
432 int p = resources.Length - 1;
433 resources [p].name = name;
434 resources [p].attrs = attribute;
436 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
438 resources [p].data = new byte [len];
439 s.Read (resources [p].data, 0, (int)len);
445 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
447 if (resources != null) {
448 MonoResource[] new_r = new MonoResource [resources.Length + 1];
449 System.Array.Copy(resources, new_r, resources.Length);
452 resources = new MonoResource [1];
454 int p = resources.Length - 1;
455 resources [p].name = name;
456 resources [p].attrs = attribute;
457 resources [p].data = blob;
461 public ModuleBuilder DefineDynamicModule (string name)
463 return DefineDynamicModule (name, name, false, true);
466 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
468 return DefineDynamicModule (name, name, emitSymbolInfo, true);
471 public ModuleBuilder DefineDynamicModule(string name, string fileName)
473 return DefineDynamicModule (name, fileName, false, false);
476 public ModuleBuilder DefineDynamicModule (string name, string fileName,
479 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
482 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
484 check_name_and_filename (name, fileName, false);
487 if (Path.GetExtension (fileName) == String.Empty)
488 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
490 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
492 throw new InvalidOperationException ("Assembly was already saved.");
495 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
497 if ((modules != null) && is_module_only)
498 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
500 if (modules != null) {
501 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
502 System.Array.Copy(modules, new_modules, modules.Length);
503 modules = new_modules;
505 modules = new ModuleBuilder [1];
507 modules [modules.Length - 1] = r;
511 public IResourceWriter DefineResource (string name, string description, string fileName)
513 return DefineResource (name, description, fileName, ResourceAttributes.Public);
516 public IResourceWriter DefineResource (string name, string description,
517 string fileName, ResourceAttributes attribute)
519 IResourceWriter writer;
521 // description seems to be ignored
522 AddResourceFile (name, fileName, attribute, false);
523 writer = new ResourceWriter (fileName);
524 if (resource_writers == null)
525 resource_writers = new ArrayList ();
526 resource_writers.Add (writer);
530 private void AddUnmanagedResource (Win32Resource res) {
531 MemoryStream ms = new MemoryStream ();
534 if (win32_resources != null) {
535 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
536 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
537 win32_resources = new_res;
540 win32_resources = new MonoWin32Resource [1];
542 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
545 [MonoTODO ("Not currently implemenented")]
546 public void DefineUnmanagedResource (byte[] resource)
548 if (resource == null)
549 throw new ArgumentNullException ("resource");
550 if (native_resource != NativeResourceType.None)
551 throw new ArgumentException ("Native resource has already been defined.");
553 // avoid definition of more than one unmanaged resource
554 native_resource = NativeResourceType.Unmanaged;
557 * The format of the argument byte array is not documented
558 * so this method is impossible to implement.
560 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
563 throw new NotImplementedException ();
566 public void DefineUnmanagedResource (string resourceFileName)
568 if (resourceFileName == null)
569 throw new ArgumentNullException ("resourceFileName");
570 if (resourceFileName.Length == 0)
571 throw new ArgumentException ("resourceFileName");
572 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
573 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
574 if (native_resource != NativeResourceType.None)
575 throw new ArgumentException ("Native resource has already been defined.");
577 // avoid definition of more than one unmanaged resource
578 native_resource = NativeResourceType.Unmanaged;
580 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
581 Win32ResFileReader reader = new Win32ResFileReader (fs);
583 foreach (Win32EncodedResource res in reader.ReadResources ()) {
584 if (res.Name.IsName || res.Type.IsName)
585 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
587 AddUnmanagedResource (res);
592 public void DefineVersionInfoResource ()
594 if (native_resource != NativeResourceType.None)
595 throw new ArgumentException ("Native resource has already been defined.");
597 // avoid definition of more than one unmanaged resource
598 native_resource = NativeResourceType.Assembly;
600 version_res = new Win32VersionResource (1, 0, false);
603 public void DefineVersionInfoResource (string product, string productVersion,
604 string company, string copyright, string trademark)
606 if (native_resource != NativeResourceType.None)
607 throw new ArgumentException ("Native resource has already been defined.");
609 // avoid definition of more than one unmanaged resource
610 native_resource = NativeResourceType.Explicit;
613 * We can only create the resource later, when the file name and
614 * the binary version is known.
617 version_res = new Win32VersionResource (1, 0, false);
618 version_res.ProductName = product != null ? product : " ";
619 version_res.ProductVersion = productVersion != null ? productVersion : " ";
620 version_res.CompanyName = company != null ? company : " ";
621 version_res.LegalCopyright = copyright != null ? copyright : " ";
622 version_res.LegalTrademarks = trademark != null ? trademark : " ";
625 private void DefineVersionInfoResourceImpl (string fileName)
627 if (versioninfo_culture != null)
628 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
629 version_res.Version = version == null ? "0.0.0.0" : version;
631 if (cattrs != null) {
632 switch (native_resource) {
633 case NativeResourceType.Assembly:
634 foreach (CustomAttributeBuilder cb in cattrs) {
635 string attrname = cb.Ctor.ReflectedType.FullName;
637 if (attrname == "System.Reflection.AssemblyProductAttribute")
638 version_res.ProductName = cb.string_arg ();
639 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
640 version_res.CompanyName = cb.string_arg ();
641 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
642 version_res.LegalCopyright = cb.string_arg ();
643 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
644 version_res.LegalTrademarks = cb.string_arg ();
645 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
646 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
647 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
648 version_res.FileVersion = cb.string_arg ();
649 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
650 version_res.ProductVersion = cb.string_arg ();
651 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
652 version_res.FileDescription = cb.string_arg ();
653 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
654 version_res.Comments = cb.string_arg ();
657 case NativeResourceType.Explicit:
658 foreach (CustomAttributeBuilder cb in cattrs) {
659 string attrname = cb.Ctor.ReflectedType.FullName;
661 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
662 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
663 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
664 version_res.Comments = cb.string_arg ();
670 version_res.OriginalFilename = fileName;
671 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
673 AddUnmanagedResource (version_res);
676 public ModuleBuilder GetDynamicModule (string name)
679 throw new ArgumentNullException ("name");
680 if (name.Length == 0)
681 throw new ArgumentException ("Empty name is not legal.", "name");
684 for (int i = 0; i < modules.Length; ++i)
685 if (modules [i].name == name)
690 public override Type[] GetExportedTypes ()
692 throw not_supported ();
695 public override FileStream GetFile (string name)
697 throw not_supported ();
700 public override FileStream[] GetFiles(bool getResourceModules) {
701 throw not_supported ();
704 internal override Module[] GetModulesInternal () {
706 return new Module [0];
708 return (Module[])modules.Clone ();
711 internal override Type[] GetTypes (bool exportedOnly) {
713 if (modules != null) {
714 for (int i = 0; i < modules.Length; ++i) {
715 Type[] types = modules [i].GetTypes ();
719 Type[] tmp = new Type [res.Length + types.Length];
720 Array.Copy (res, 0, tmp, 0, res.Length);
721 Array.Copy (types, 0, tmp, res.Length, types.Length);
725 if (loaded_modules != null) {
726 for (int i = 0; i < loaded_modules.Length; ++i) {
727 Type[] types = loaded_modules [i].GetTypes ();
731 Type[] tmp = new Type [res.Length + types.Length];
732 Array.Copy (res, 0, tmp, 0, res.Length);
733 Array.Copy (types, 0, tmp, res.Length, types.Length);
739 List<Exception> exceptions = null;
740 foreach (var type in res) {
741 if (type is TypeBuilder) {
742 if (exceptions == null)
743 exceptions = new List <Exception> ();
744 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
747 if (exceptions != null)
748 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
751 return res == null ? Type.EmptyTypes : res;
754 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
755 throw not_supported ();
758 public override string[] GetManifestResourceNames() {
759 throw not_supported ();
762 public override Stream GetManifestResourceStream(string name) {
763 throw not_supported ();
765 public override Stream GetManifestResourceStream(Type type, string name) {
766 throw not_supported ();
769 internal bool IsSave {
771 return access != (uint)AssemblyBuilderAccess.Run;
775 internal bool IsRun {
777 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
779 || access == (uint)AssemblyBuilderAccess.RunAndCollect
786 internal bool IsCollectible {
788 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
792 internal string AssemblyDir {
799 * Mono extension. If this is set, the assembly can only contain one
800 * module, access should be Save, and the saved image will not contain an
803 internal bool IsModuleOnly {
805 return is_module_only;
808 is_module_only = value;
812 ModuleBuilder manifest_module;
815 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
816 // on an assemblybuilder.
818 internal override Module GetManifestModule () {
819 if (manifest_module == null)
820 manifest_module = DefineDynamicModule ("Default Dynamic Module");
821 return manifest_module;
824 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
826 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
828 this.peKind = portableExecutableKind;
829 this.machine = imageFileMachine;
831 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
832 throw new NotImplementedException (peKind.ToString ());
833 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
834 throw new NotImplementedException (machine.ToString ());
836 if (resource_writers != null) {
837 foreach (IResourceWriter writer in resource_writers) {
843 // Create a main module if not already created
844 ModuleBuilder mainModule = null;
845 if (modules != null) {
846 foreach (ModuleBuilder module in modules)
847 if (module.FullyQualifiedName == assemblyFileName)
850 if (mainModule == null)
851 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
854 mainModule.IsMain = true;
857 * Create a new entry point if the one specified
858 * by the user is in another module.
860 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
862 if (entry_point.GetParametersCount () == 1)
863 paramTypes = new Type [] { typeof (string) };
865 paramTypes = Type.EmptyTypes;
867 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
868 ILGenerator ilgen = mb.GetILGenerator ();
869 if (paramTypes.Length == 1)
870 ilgen.Emit (OpCodes.Ldarg_0);
871 ilgen.Emit (OpCodes.Tailcall);
872 ilgen.Emit (OpCodes.Call, entry_point);
873 ilgen.Emit (OpCodes.Ret);
878 if (version_res != null)
879 DefineVersionInfoResourceImpl (assemblyFileName);
882 // runtime needs to value to embed it into the assembly
883 public_key = sn.PublicKey;
886 foreach (ModuleBuilder module in modules)
887 if (module != mainModule)
890 // Write out the main module at the end, because it needs to
891 // contain the hash of the other modules
894 if ((sn != null) && (sn.CanSign)) {
895 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
901 public void Save (string assemblyFileName)
903 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
906 public void SetEntryPoint (MethodInfo entryMethod)
908 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
911 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
913 if (entryMethod == null)
914 throw new ArgumentNullException ("entryMethod");
915 if (entryMethod.DeclaringType.Assembly != this)
916 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
918 entry_point = entryMethod;
922 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
924 if (customBuilder == null)
925 throw new ArgumentNullException ("customBuilder");
927 if (cattrs != null) {
928 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
929 cattrs.CopyTo (new_array, 0);
930 new_array [cattrs.Length] = customBuilder;
933 cattrs = new CustomAttributeBuilder [1];
934 cattrs [0] = customBuilder;
939 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
941 throw new ArgumentNullException ("con");
942 if (binaryAttribute == null)
943 throw new ArgumentNullException ("binaryAttribute");
945 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
948 private Exception not_supported () {
949 // Strange message but this is what MS.NET prints...
950 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
953 private void check_name_and_filename (string name, string fileName,
954 bool fileNeedsToExists) {
956 throw new ArgumentNullException ("name");
957 if (fileName == null)
958 throw new ArgumentNullException ("fileName");
959 if (name.Length == 0)
960 throw new ArgumentException ("Empty name is not legal.", "name");
961 if (fileName.Length == 0)
962 throw new ArgumentException ("Empty file name is not legal.", "fileName");
963 if (Path.GetFileName (fileName) != fileName)
964 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
966 // Resource files are created/searched under the assembly storage
968 string fullFileName = fileName;
970 fullFileName = Path.Combine (dir, fileName);
972 if (fileNeedsToExists && !File.Exists (fullFileName))
973 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
975 if (resources != null) {
976 for (int i = 0; i < resources.Length; ++i) {
977 if (resources [i].filename == fullFileName)
978 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
979 if (resources [i].name == name)
980 throw new ArgumentException ("Duplicate name '" + name + "'");
984 if (modules != null) {
985 for (int i = 0; i < modules.Length; ++i) {
986 // Use fileName instead of fullFileName here
987 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
988 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
989 if (modules [i].Name == name)
990 throw new ArgumentException ("Duplicate name '" + name + "'");
995 private String create_assembly_version (String version) {
996 String[] parts = version.Split ('.');
997 int[] ver = new int [4] { 0, 0, 0, 0 };
999 if ((parts.Length < 0) || (parts.Length > 4))
1000 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1002 for (int i = 0; i < parts.Length; ++i) {
1003 if (parts [i] == "*") {
1004 DateTime now = DateTime.Now;
1007 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1008 if (parts.Length == 3)
1009 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1013 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1015 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1019 ver [i] = Int32.Parse (parts [i]);
1021 catch (FormatException) {
1022 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1027 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1030 private string GetCultureString (string str)
1032 return (str == "neutral" ? String.Empty : str);
1035 internal override AssemblyName UnprotectedGetName ()
1037 AssemblyName an = base.UnprotectedGetName ();
1039 an.SetPublicKey (sn.PublicKey);
1040 an.SetPublicKeyToken (sn.PublicKeyToken);
1045 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1046 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1048 return new MonoGenericClass (gtd, typeArguments);
1051 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1053 throw new NotImplementedException ();
1056 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1058 throw new NotImplementedException ();
1061 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1063 throw new NotImplementedException ();
1066 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1068 throw new NotImplementedException ();
1072 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1075 throw new ArgumentNullException (name);
1076 if (name.Length == 0)
1077 throw new ArgumentException ("name", "Name cannot be empty");
1079 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1080 if (res is TypeBuilder) {
1082 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1088 public override Module GetModule (String name)
1091 throw new ArgumentNullException ("name");
1092 if (name.Length == 0)
1093 throw new ArgumentException ("Name can't be empty");
1095 if (modules == null)
1098 foreach (Module module in modules) {
1099 if (module.ScopeName == name)
1106 public override Module[] GetModules (bool getResourceModules)
1108 Module[] modules = GetModulesInternal ();
1110 if (!getResourceModules) {
1111 var result = new List<Module> (modules.Length);
1112 foreach (Module m in modules)
1113 if (!m.IsResource ())
1115 return result.ToArray ();
1120 public override AssemblyName GetName (bool copiedName)
1122 return base.GetName (copiedName);
1125 [MonoTODO ("This always returns an empty array")]
1126 public override AssemblyName[] GetReferencedAssemblies () {
1127 return GetReferencedAssemblies (this);
1130 public override Module[] GetLoadedModules (bool getResourceModules)
1132 return GetModules (getResourceModules);
1135 //FIXME MS has issues loading satelite assemblies from SRE
1136 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1138 return GetSatelliteAssembly (culture, null, true);
1141 //FIXME MS has issues loading satelite assemblies from SRE
1142 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1144 return GetSatelliteAssembly (culture, version, true);
1147 public override Module ManifestModule {
1149 return GetManifestModule ();
1153 public override bool GlobalAssemblyCache {
1159 public override bool IsDynamic {
1160 get { return true; }
1163 public override bool Equals (object obj)
1165 return base.Equals (obj);
1168 public override int GetHashCode ()
1170 return base.GetHashCode ();
1173 public override bool IsDefined (Type attributeType, bool inherit)
1175 return base.IsDefined (attributeType, inherit);
1178 public override object[] GetCustomAttributes (bool inherit)
1180 return base.GetCustomAttributes (inherit);
1183 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1185 return base.GetCustomAttributes (attributeType, inherit);
1188 public override string FullName {
1189 get { return base.FullName; }