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 static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access)
464 throw new ArgumentNullException ("name");
466 return new AssemblyBuilder (name, null, access, false);
469 public ModuleBuilder DefineDynamicModule (string name)
471 return DefineDynamicModule (name, name, false, true);
474 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
476 return DefineDynamicModule (name, name, emitSymbolInfo, true);
479 public ModuleBuilder DefineDynamicModule(string name, string fileName)
481 return DefineDynamicModule (name, fileName, false, false);
484 public ModuleBuilder DefineDynamicModule (string name, string fileName,
487 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
490 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
492 check_name_and_filename (name, fileName, false);
495 if (Path.GetExtension (fileName) == String.Empty)
496 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
498 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
500 throw new InvalidOperationException ("Assembly was already saved.");
503 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
505 if ((modules != null) && is_module_only)
506 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
508 if (modules != null) {
509 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
510 System.Array.Copy(modules, new_modules, modules.Length);
511 modules = new_modules;
513 modules = new ModuleBuilder [1];
515 modules [modules.Length - 1] = r;
519 public IResourceWriter DefineResource (string name, string description, string fileName)
521 return DefineResource (name, description, fileName, ResourceAttributes.Public);
524 public IResourceWriter DefineResource (string name, string description,
525 string fileName, ResourceAttributes attribute)
527 IResourceWriter writer;
529 // description seems to be ignored
530 AddResourceFile (name, fileName, attribute, false);
531 writer = new ResourceWriter (fileName);
532 if (resource_writers == null)
533 resource_writers = new ArrayList ();
534 resource_writers.Add (writer);
538 private void AddUnmanagedResource (Win32Resource res) {
539 MemoryStream ms = new MemoryStream ();
542 if (win32_resources != null) {
543 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
544 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
545 win32_resources = new_res;
548 win32_resources = new MonoWin32Resource [1];
550 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
553 [MonoTODO ("Not currently implemenented")]
554 public void DefineUnmanagedResource (byte[] resource)
556 if (resource == null)
557 throw new ArgumentNullException ("resource");
558 if (native_resource != NativeResourceType.None)
559 throw new ArgumentException ("Native resource has already been defined.");
561 // avoid definition of more than one unmanaged resource
562 native_resource = NativeResourceType.Unmanaged;
565 * The format of the argument byte array is not documented
566 * so this method is impossible to implement.
568 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
571 throw new NotImplementedException ();
574 public void DefineUnmanagedResource (string resourceFileName)
576 if (resourceFileName == null)
577 throw new ArgumentNullException ("resourceFileName");
578 if (resourceFileName.Length == 0)
579 throw new ArgumentException ("resourceFileName");
580 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
581 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
582 if (native_resource != NativeResourceType.None)
583 throw new ArgumentException ("Native resource has already been defined.");
585 // avoid definition of more than one unmanaged resource
586 native_resource = NativeResourceType.Unmanaged;
588 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
589 Win32ResFileReader reader = new Win32ResFileReader (fs);
591 foreach (Win32EncodedResource res in reader.ReadResources ()) {
592 if (res.Name.IsName || res.Type.IsName)
593 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
595 AddUnmanagedResource (res);
600 public void DefineVersionInfoResource ()
602 if (native_resource != NativeResourceType.None)
603 throw new ArgumentException ("Native resource has already been defined.");
605 // avoid definition of more than one unmanaged resource
606 native_resource = NativeResourceType.Assembly;
608 version_res = new Win32VersionResource (1, 0, false);
611 public void DefineVersionInfoResource (string product, string productVersion,
612 string company, string copyright, string trademark)
614 if (native_resource != NativeResourceType.None)
615 throw new ArgumentException ("Native resource has already been defined.");
617 // avoid definition of more than one unmanaged resource
618 native_resource = NativeResourceType.Explicit;
621 * We can only create the resource later, when the file name and
622 * the binary version is known.
625 version_res = new Win32VersionResource (1, 0, false);
626 version_res.ProductName = product != null ? product : " ";
627 version_res.ProductVersion = productVersion != null ? productVersion : " ";
628 version_res.CompanyName = company != null ? company : " ";
629 version_res.LegalCopyright = copyright != null ? copyright : " ";
630 version_res.LegalTrademarks = trademark != null ? trademark : " ";
633 private void DefineVersionInfoResourceImpl (string fileName)
635 if (versioninfo_culture != null)
636 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
637 version_res.Version = version == null ? "0.0.0.0" : version;
639 if (cattrs != null) {
640 switch (native_resource) {
641 case NativeResourceType.Assembly:
642 foreach (CustomAttributeBuilder cb in cattrs) {
643 string attrname = cb.Ctor.ReflectedType.FullName;
645 if (attrname == "System.Reflection.AssemblyProductAttribute")
646 version_res.ProductName = cb.string_arg ();
647 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
648 version_res.CompanyName = cb.string_arg ();
649 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
650 version_res.LegalCopyright = cb.string_arg ();
651 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
652 version_res.LegalTrademarks = cb.string_arg ();
653 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
654 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
655 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
656 version_res.FileVersion = cb.string_arg ();
657 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
658 version_res.ProductVersion = cb.string_arg ();
659 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
660 version_res.FileDescription = cb.string_arg ();
661 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
662 version_res.Comments = cb.string_arg ();
665 case NativeResourceType.Explicit:
666 foreach (CustomAttributeBuilder cb in cattrs) {
667 string attrname = cb.Ctor.ReflectedType.FullName;
669 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
670 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
671 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
672 version_res.Comments = cb.string_arg ();
678 version_res.OriginalFilename = fileName;
679 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
681 AddUnmanagedResource (version_res);
684 public ModuleBuilder GetDynamicModule (string name)
687 throw new ArgumentNullException ("name");
688 if (name.Length == 0)
689 throw new ArgumentException ("Empty name is not legal.", "name");
692 for (int i = 0; i < modules.Length; ++i)
693 if (modules [i].name == name)
698 public override Type[] GetExportedTypes ()
700 throw not_supported ();
703 public override FileStream GetFile (string name)
705 throw not_supported ();
708 public override FileStream[] GetFiles(bool getResourceModules) {
709 throw not_supported ();
712 internal override Module[] GetModulesInternal () {
714 return new Module [0];
716 return (Module[])modules.Clone ();
719 internal override Type[] GetTypes (bool exportedOnly) {
721 if (modules != null) {
722 for (int i = 0; i < modules.Length; ++i) {
723 Type[] types = modules [i].GetTypes ();
727 Type[] tmp = new Type [res.Length + types.Length];
728 Array.Copy (res, 0, tmp, 0, res.Length);
729 Array.Copy (types, 0, tmp, res.Length, types.Length);
733 if (loaded_modules != null) {
734 for (int i = 0; i < loaded_modules.Length; ++i) {
735 Type[] types = loaded_modules [i].GetTypes ();
739 Type[] tmp = new Type [res.Length + types.Length];
740 Array.Copy (res, 0, tmp, 0, res.Length);
741 Array.Copy (types, 0, tmp, res.Length, types.Length);
747 List<Exception> exceptions = null;
748 foreach (var type in res) {
749 if (type is TypeBuilder) {
750 if (exceptions == null)
751 exceptions = new List <Exception> ();
752 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
755 if (exceptions != null)
756 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
759 return res == null ? Type.EmptyTypes : res;
762 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
763 throw not_supported ();
766 public override string[] GetManifestResourceNames() {
767 throw not_supported ();
770 public override Stream GetManifestResourceStream(string name) {
771 throw not_supported ();
773 public override Stream GetManifestResourceStream(Type type, string name) {
774 throw not_supported ();
777 internal bool IsSave {
779 return access != (uint)AssemblyBuilderAccess.Run;
783 internal bool IsRun {
785 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
786 || access == (uint)AssemblyBuilderAccess.RunAndCollect
792 internal bool IsCollectible {
794 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
798 internal string AssemblyDir {
805 * Mono extension. If this is set, the assembly can only contain one
806 * module, access should be Save, and the saved image will not contain an
809 internal bool IsModuleOnly {
811 return is_module_only;
814 is_module_only = value;
818 ModuleBuilder manifest_module;
821 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
822 // on an assemblybuilder.
824 internal override Module GetManifestModule () {
825 if (manifest_module == null)
826 manifest_module = DefineDynamicModule ("Default Dynamic Module");
827 return manifest_module;
830 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
832 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
834 this.peKind = portableExecutableKind;
835 this.machine = imageFileMachine;
837 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
838 throw new NotImplementedException (peKind.ToString ());
839 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
840 throw new NotImplementedException (machine.ToString ());
842 if (resource_writers != null) {
843 foreach (IResourceWriter writer in resource_writers) {
849 // Create a main module if not already created
850 ModuleBuilder mainModule = null;
851 if (modules != null) {
852 foreach (ModuleBuilder module in modules)
853 if (module.FullyQualifiedName == assemblyFileName)
856 if (mainModule == null)
857 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
860 mainModule.IsMain = true;
863 * Create a new entry point if the one specified
864 * by the user is in another module.
866 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
868 if (entry_point.GetParametersCount () == 1)
869 paramTypes = new Type [] { typeof (string) };
871 paramTypes = Type.EmptyTypes;
873 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
874 ILGenerator ilgen = mb.GetILGenerator ();
875 if (paramTypes.Length == 1)
876 ilgen.Emit (OpCodes.Ldarg_0);
877 ilgen.Emit (OpCodes.Tailcall);
878 ilgen.Emit (OpCodes.Call, entry_point);
879 ilgen.Emit (OpCodes.Ret);
884 if (version_res != null)
885 DefineVersionInfoResourceImpl (assemblyFileName);
888 // runtime needs to value to embed it into the assembly
889 public_key = sn.PublicKey;
892 foreach (ModuleBuilder module in modules)
893 if (module != mainModule)
896 // Write out the main module at the end, because it needs to
897 // contain the hash of the other modules
900 if ((sn != null) && (sn.CanSign)) {
901 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
907 public void Save (string assemblyFileName)
909 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
912 public void SetEntryPoint (MethodInfo entryMethod)
914 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
917 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
919 if (entryMethod == null)
920 throw new ArgumentNullException ("entryMethod");
921 if (entryMethod.DeclaringType.Assembly != this)
922 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
924 entry_point = entryMethod;
928 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
930 if (customBuilder == null)
931 throw new ArgumentNullException ("customBuilder");
933 if (cattrs != null) {
934 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
935 cattrs.CopyTo (new_array, 0);
936 new_array [cattrs.Length] = customBuilder;
939 cattrs = new CustomAttributeBuilder [1];
940 cattrs [0] = customBuilder;
945 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
947 throw new ArgumentNullException ("con");
948 if (binaryAttribute == null)
949 throw new ArgumentNullException ("binaryAttribute");
951 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
954 private Exception not_supported () {
955 // Strange message but this is what MS.NET prints...
956 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
959 private void check_name_and_filename (string name, string fileName,
960 bool fileNeedsToExists) {
962 throw new ArgumentNullException ("name");
963 if (fileName == null)
964 throw new ArgumentNullException ("fileName");
965 if (name.Length == 0)
966 throw new ArgumentException ("Empty name is not legal.", "name");
967 if (fileName.Length == 0)
968 throw new ArgumentException ("Empty file name is not legal.", "fileName");
969 if (Path.GetFileName (fileName) != fileName)
970 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
972 // Resource files are created/searched under the assembly storage
974 string fullFileName = fileName;
976 fullFileName = Path.Combine (dir, fileName);
978 if (fileNeedsToExists && !File.Exists (fullFileName))
979 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
981 if (resources != null) {
982 for (int i = 0; i < resources.Length; ++i) {
983 if (resources [i].filename == fullFileName)
984 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
985 if (resources [i].name == name)
986 throw new ArgumentException ("Duplicate name '" + name + "'");
990 if (modules != null) {
991 for (int i = 0; i < modules.Length; ++i) {
992 // Use fileName instead of fullFileName here
993 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
994 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
995 if (modules [i].Name == name)
996 throw new ArgumentException ("Duplicate name '" + name + "'");
1001 private String create_assembly_version (String version) {
1002 String[] parts = version.Split ('.');
1003 int[] ver = new int [4] { 0, 0, 0, 0 };
1005 if ((parts.Length < 0) || (parts.Length > 4))
1006 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1008 for (int i = 0; i < parts.Length; ++i) {
1009 if (parts [i] == "*") {
1010 DateTime now = DateTime.Now;
1013 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1014 if (parts.Length == 3)
1015 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1019 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1021 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1025 ver [i] = Int32.Parse (parts [i]);
1027 catch (FormatException) {
1028 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1033 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1036 private string GetCultureString (string str)
1038 return (str == "neutral" ? String.Empty : str);
1041 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1042 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1044 return new MonoGenericClass (gtd, typeArguments);
1047 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1049 throw new NotImplementedException ();
1052 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1054 throw new NotImplementedException ();
1057 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1059 throw new NotImplementedException ();
1062 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1064 throw new NotImplementedException ();
1067 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1070 throw new ArgumentNullException (name);
1071 if (name.Length == 0)
1072 throw new ArgumentException ("name", "Name cannot be empty");
1074 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1075 if (res is TypeBuilder) {
1077 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1083 public override Module GetModule (String name)
1086 throw new ArgumentNullException ("name");
1087 if (name.Length == 0)
1088 throw new ArgumentException ("Name can't be empty");
1090 if (modules == null)
1093 foreach (Module module in modules) {
1094 if (module.ScopeName == name)
1101 public override Module[] GetModules (bool getResourceModules)
1103 Module[] modules = GetModulesInternal ();
1105 if (!getResourceModules) {
1106 var result = new List<Module> (modules.Length);
1107 foreach (Module m in modules)
1108 if (!m.IsResource ())
1110 return result.ToArray ();
1115 public override AssemblyName GetName (bool copiedName)
1117 var aname = AssemblyName.Create (this, false);
1120 aname.SetPublicKey (sn.PublicKey);
1121 aname.SetPublicKeyToken (sn.PublicKeyToken);
1127 [MonoTODO ("This always returns an empty array")]
1128 public override AssemblyName[] GetReferencedAssemblies () {
1129 return GetReferencedAssemblies (this);
1132 public override Module[] GetLoadedModules (bool getResourceModules)
1134 return GetModules (getResourceModules);
1137 //FIXME MS has issues loading satelite assemblies from SRE
1138 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1140 return GetSatelliteAssembly (culture, null, true);
1143 //FIXME MS has issues loading satelite assemblies from SRE
1144 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1146 return GetSatelliteAssembly (culture, version, true);
1149 public override Module ManifestModule {
1151 return GetManifestModule ();
1155 public override bool GlobalAssemblyCache {
1161 public override bool IsDynamic {
1162 get { return true; }
1165 public override bool Equals (object obj)
1167 return base.Equals (obj);
1170 public override int GetHashCode ()
1172 return base.GetHashCode ();
1175 public override bool IsDefined (Type attributeType, bool inherit)
1177 return base.IsDefined (attributeType, inherit);
1180 public override object[] GetCustomAttributes (bool inherit)
1182 return base.GetCustomAttributes (inherit);
1185 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1187 return base.GetCustomAttributes (attributeType, inherit);
1190 public override string FullName {
1191 get { return base.FullName; }