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 static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access, IEnumerable<CustomAttributeBuilder> assemblyAttributes)
471 var ab = DefineDynamicAssembly (name, access);
472 foreach (var attr in assemblyAttributes) {
473 ab.SetCustomAttribute (attr);
479 public ModuleBuilder DefineDynamicModule (string name)
481 return DefineDynamicModule (name, name, false, true);
484 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
486 return DefineDynamicModule (name, name, emitSymbolInfo, true);
489 public ModuleBuilder DefineDynamicModule(string name, string fileName)
491 return DefineDynamicModule (name, fileName, false, false);
494 public ModuleBuilder DefineDynamicModule (string name, string fileName,
497 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
500 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
502 check_name_and_filename (name, fileName, false);
505 if (Path.GetExtension (fileName) == String.Empty)
506 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
508 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
510 throw new InvalidOperationException ("Assembly was already saved.");
513 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
515 if ((modules != null) && is_module_only)
516 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
518 if (modules != null) {
519 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
520 System.Array.Copy(modules, new_modules, modules.Length);
521 modules = new_modules;
523 modules = new ModuleBuilder [1];
525 modules [modules.Length - 1] = r;
529 public IResourceWriter DefineResource (string name, string description, string fileName)
531 return DefineResource (name, description, fileName, ResourceAttributes.Public);
534 public IResourceWriter DefineResource (string name, string description,
535 string fileName, ResourceAttributes attribute)
537 IResourceWriter writer;
539 // description seems to be ignored
540 AddResourceFile (name, fileName, attribute, false);
541 writer = new ResourceWriter (fileName);
542 if (resource_writers == null)
543 resource_writers = new ArrayList ();
544 resource_writers.Add (writer);
548 private void AddUnmanagedResource (Win32Resource res) {
549 MemoryStream ms = new MemoryStream ();
552 if (win32_resources != null) {
553 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
554 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
555 win32_resources = new_res;
558 win32_resources = new MonoWin32Resource [1];
560 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
563 [MonoTODO ("Not currently implemenented")]
564 public void DefineUnmanagedResource (byte[] resource)
566 if (resource == null)
567 throw new ArgumentNullException ("resource");
568 if (native_resource != NativeResourceType.None)
569 throw new ArgumentException ("Native resource has already been defined.");
571 // avoid definition of more than one unmanaged resource
572 native_resource = NativeResourceType.Unmanaged;
575 * The format of the argument byte array is not documented
576 * so this method is impossible to implement.
578 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
581 throw new NotImplementedException ();
584 public void DefineUnmanagedResource (string resourceFileName)
586 if (resourceFileName == null)
587 throw new ArgumentNullException ("resourceFileName");
588 if (resourceFileName.Length == 0)
589 throw new ArgumentException ("resourceFileName");
590 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
591 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
592 if (native_resource != NativeResourceType.None)
593 throw new ArgumentException ("Native resource has already been defined.");
595 // avoid definition of more than one unmanaged resource
596 native_resource = NativeResourceType.Unmanaged;
598 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
599 Win32ResFileReader reader = new Win32ResFileReader (fs);
601 foreach (Win32EncodedResource res in reader.ReadResources ()) {
602 if (res.Name.IsName || res.Type.IsName)
603 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
605 AddUnmanagedResource (res);
610 public void DefineVersionInfoResource ()
612 if (native_resource != NativeResourceType.None)
613 throw new ArgumentException ("Native resource has already been defined.");
615 // avoid definition of more than one unmanaged resource
616 native_resource = NativeResourceType.Assembly;
618 version_res = new Win32VersionResource (1, 0, false);
621 public void DefineVersionInfoResource (string product, string productVersion,
622 string company, string copyright, string trademark)
624 if (native_resource != NativeResourceType.None)
625 throw new ArgumentException ("Native resource has already been defined.");
627 // avoid definition of more than one unmanaged resource
628 native_resource = NativeResourceType.Explicit;
631 * We can only create the resource later, when the file name and
632 * the binary version is known.
635 version_res = new Win32VersionResource (1, 0, false);
636 version_res.ProductName = product != null ? product : " ";
637 version_res.ProductVersion = productVersion != null ? productVersion : " ";
638 version_res.CompanyName = company != null ? company : " ";
639 version_res.LegalCopyright = copyright != null ? copyright : " ";
640 version_res.LegalTrademarks = trademark != null ? trademark : " ";
643 private void DefineVersionInfoResourceImpl (string fileName)
645 if (versioninfo_culture != null)
646 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
647 version_res.Version = version == null ? "0.0.0.0" : version;
649 if (cattrs != null) {
650 switch (native_resource) {
651 case NativeResourceType.Assembly:
652 foreach (CustomAttributeBuilder cb in cattrs) {
653 string attrname = cb.Ctor.ReflectedType.FullName;
655 if (attrname == "System.Reflection.AssemblyProductAttribute")
656 version_res.ProductName = cb.string_arg ();
657 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
658 version_res.CompanyName = cb.string_arg ();
659 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
660 version_res.LegalCopyright = cb.string_arg ();
661 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
662 version_res.LegalTrademarks = cb.string_arg ();
663 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
664 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
665 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
666 version_res.FileVersion = cb.string_arg ();
667 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
668 version_res.ProductVersion = cb.string_arg ();
669 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
670 version_res.FileDescription = cb.string_arg ();
671 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
672 version_res.Comments = cb.string_arg ();
675 case NativeResourceType.Explicit:
676 foreach (CustomAttributeBuilder cb in cattrs) {
677 string attrname = cb.Ctor.ReflectedType.FullName;
679 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
680 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
681 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
682 version_res.Comments = cb.string_arg ();
688 version_res.OriginalFilename = fileName;
689 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
691 AddUnmanagedResource (version_res);
694 public ModuleBuilder GetDynamicModule (string name)
697 throw new ArgumentNullException ("name");
698 if (name.Length == 0)
699 throw new ArgumentException ("Empty name is not legal.", "name");
702 for (int i = 0; i < modules.Length; ++i)
703 if (modules [i].name == name)
708 public override Type[] GetExportedTypes ()
710 throw not_supported ();
713 public override FileStream GetFile (string name)
715 throw not_supported ();
718 public override FileStream[] GetFiles(bool getResourceModules) {
719 throw not_supported ();
722 internal override Module[] GetModulesInternal () {
724 return new Module [0];
726 return (Module[])modules.Clone ();
729 internal override Type[] GetTypes (bool exportedOnly) {
731 if (modules != null) {
732 for (int i = 0; i < modules.Length; ++i) {
733 Type[] types = modules [i].GetTypes ();
737 Type[] tmp = new Type [res.Length + types.Length];
738 Array.Copy (res, 0, tmp, 0, res.Length);
739 Array.Copy (types, 0, tmp, res.Length, types.Length);
743 if (loaded_modules != null) {
744 for (int i = 0; i < loaded_modules.Length; ++i) {
745 Type[] types = loaded_modules [i].GetTypes ();
749 Type[] tmp = new Type [res.Length + types.Length];
750 Array.Copy (res, 0, tmp, 0, res.Length);
751 Array.Copy (types, 0, tmp, res.Length, types.Length);
757 List<Exception> exceptions = null;
758 foreach (var type in res) {
759 if (type is TypeBuilder) {
760 if (exceptions == null)
761 exceptions = new List <Exception> ();
762 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
765 if (exceptions != null)
766 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
769 return res == null ? Type.EmptyTypes : res;
772 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
773 throw not_supported ();
776 public override string[] GetManifestResourceNames() {
777 throw not_supported ();
780 public override Stream GetManifestResourceStream(string name) {
781 throw not_supported ();
783 public override Stream GetManifestResourceStream(Type type, string name) {
784 throw not_supported ();
787 internal bool IsSave {
789 return access != (uint)AssemblyBuilderAccess.Run;
793 internal bool IsRun {
795 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
796 || access == (uint)AssemblyBuilderAccess.RunAndCollect
802 internal bool IsCollectible {
804 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
808 internal string AssemblyDir {
815 * Mono extension. If this is set, the assembly can only contain one
816 * module, access should be Save, and the saved image will not contain an
819 internal bool IsModuleOnly {
821 return is_module_only;
824 is_module_only = value;
828 ModuleBuilder manifest_module;
831 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
832 // on an assemblybuilder.
834 internal override Module GetManifestModule () {
835 if (manifest_module == null)
836 manifest_module = DefineDynamicModule ("Default Dynamic Module");
837 return manifest_module;
840 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
842 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
844 this.peKind = portableExecutableKind;
845 this.machine = imageFileMachine;
847 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
848 throw new NotImplementedException (peKind.ToString ());
849 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
850 throw new NotImplementedException (machine.ToString ());
852 if (resource_writers != null) {
853 foreach (IResourceWriter writer in resource_writers) {
859 // Create a main module if not already created
860 ModuleBuilder mainModule = null;
861 if (modules != null) {
862 foreach (ModuleBuilder module in modules)
863 if (module.FullyQualifiedName == assemblyFileName)
866 if (mainModule == null)
867 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
870 mainModule.IsMain = true;
873 * Create a new entry point if the one specified
874 * by the user is in another module.
876 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
878 if (entry_point.GetParametersCount () == 1)
879 paramTypes = new Type [] { typeof (string) };
881 paramTypes = Type.EmptyTypes;
883 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
884 ILGenerator ilgen = mb.GetILGenerator ();
885 if (paramTypes.Length == 1)
886 ilgen.Emit (OpCodes.Ldarg_0);
887 ilgen.Emit (OpCodes.Tailcall);
888 ilgen.Emit (OpCodes.Call, entry_point);
889 ilgen.Emit (OpCodes.Ret);
894 if (version_res != null)
895 DefineVersionInfoResourceImpl (assemblyFileName);
898 // runtime needs to value to embed it into the assembly
899 public_key = sn.PublicKey;
902 foreach (ModuleBuilder module in modules)
903 if (module != mainModule)
906 // Write out the main module at the end, because it needs to
907 // contain the hash of the other modules
910 if ((sn != null) && (sn.CanSign)) {
911 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
917 public void Save (string assemblyFileName)
919 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
922 public void SetEntryPoint (MethodInfo entryMethod)
924 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
927 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
929 if (entryMethod == null)
930 throw new ArgumentNullException ("entryMethod");
931 if (entryMethod.DeclaringType.Assembly != this)
932 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
934 entry_point = entryMethod;
938 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
940 if (customBuilder == null)
941 throw new ArgumentNullException ("customBuilder");
943 if (cattrs != null) {
944 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
945 cattrs.CopyTo (new_array, 0);
946 new_array [cattrs.Length] = customBuilder;
949 cattrs = new CustomAttributeBuilder [1];
950 cattrs [0] = customBuilder;
955 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
957 throw new ArgumentNullException ("con");
958 if (binaryAttribute == null)
959 throw new ArgumentNullException ("binaryAttribute");
961 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
964 private Exception not_supported () {
965 // Strange message but this is what MS.NET prints...
966 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
969 private void check_name_and_filename (string name, string fileName,
970 bool fileNeedsToExists) {
972 throw new ArgumentNullException ("name");
973 if (fileName == null)
974 throw new ArgumentNullException ("fileName");
975 if (name.Length == 0)
976 throw new ArgumentException ("Empty name is not legal.", "name");
977 if (fileName.Length == 0)
978 throw new ArgumentException ("Empty file name is not legal.", "fileName");
979 if (Path.GetFileName (fileName) != fileName)
980 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
982 // Resource files are created/searched under the assembly storage
984 string fullFileName = fileName;
986 fullFileName = Path.Combine (dir, fileName);
988 if (fileNeedsToExists && !File.Exists (fullFileName))
989 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
991 if (resources != null) {
992 for (int i = 0; i < resources.Length; ++i) {
993 if (resources [i].filename == fullFileName)
994 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
995 if (resources [i].name == name)
996 throw new ArgumentException ("Duplicate name '" + name + "'");
1000 if (modules != null) {
1001 for (int i = 0; i < modules.Length; ++i) {
1002 // Use fileName instead of fullFileName here
1003 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1004 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1005 if (modules [i].Name == name)
1006 throw new ArgumentException ("Duplicate name '" + name + "'");
1011 private String create_assembly_version (String version) {
1012 String[] parts = version.Split ('.');
1013 int[] ver = new int [4] { 0, 0, 0, 0 };
1015 if ((parts.Length < 0) || (parts.Length > 4))
1016 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1018 for (int i = 0; i < parts.Length; ++i) {
1019 if (parts [i] == "*") {
1020 DateTime now = DateTime.Now;
1023 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1024 if (parts.Length == 3)
1025 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1029 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1031 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1035 ver [i] = Int32.Parse (parts [i]);
1037 catch (FormatException) {
1038 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1043 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1046 private string GetCultureString (string str)
1048 return (str == "neutral" ? String.Empty : str);
1051 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1052 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1054 return new TypeBuilderInstantiation (gtd, typeArguments);
1057 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1059 throw new NotImplementedException ();
1062 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1064 throw new NotImplementedException ();
1067 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1069 throw new NotImplementedException ();
1072 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1074 throw new NotImplementedException ();
1077 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1080 throw new ArgumentNullException (name);
1081 if (name.Length == 0)
1082 throw new ArgumentException ("name", "Name cannot be empty");
1084 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1085 if (res is TypeBuilder) {
1087 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1093 public override Module GetModule (String name)
1096 throw new ArgumentNullException ("name");
1097 if (name.Length == 0)
1098 throw new ArgumentException ("Name can't be empty");
1100 if (modules == null)
1103 foreach (Module module in modules) {
1104 if (module.ScopeName == name)
1111 public override Module[] GetModules (bool getResourceModules)
1113 Module[] modules = GetModulesInternal ();
1115 if (!getResourceModules) {
1116 var result = new List<Module> (modules.Length);
1117 foreach (Module m in modules)
1118 if (!m.IsResource ())
1120 return result.ToArray ();
1125 public override AssemblyName GetName (bool copiedName)
1127 var aname = AssemblyName.Create (this, false);
1130 aname.SetPublicKey (sn.PublicKey);
1131 aname.SetPublicKeyToken (sn.PublicKeyToken);
1137 [MonoTODO ("This always returns an empty array")]
1138 public override AssemblyName[] GetReferencedAssemblies () {
1139 return GetReferencedAssemblies (this);
1142 public override Module[] GetLoadedModules (bool getResourceModules)
1144 return GetModules (getResourceModules);
1147 //FIXME MS has issues loading satelite assemblies from SRE
1148 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1150 return GetSatelliteAssembly (culture, null, true);
1153 //FIXME MS has issues loading satelite assemblies from SRE
1154 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1156 return GetSatelliteAssembly (culture, version, true);
1159 public override Module ManifestModule {
1161 return GetManifestModule ();
1165 public override bool GlobalAssemblyCache {
1171 public override bool IsDynamic {
1172 get { return true; }
1175 public override bool Equals (object obj)
1177 return base.Equals (obj);
1180 public override int GetHashCode ()
1182 return base.GetHashCode ();
1185 public override bool IsDefined (Type attributeType, bool inherit)
1187 return base.IsDefined (attributeType, inherit);
1190 public override object[] GetCustomAttributes (bool inherit)
1192 return base.GetCustomAttributes (inherit);
1195 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1197 return base.GetCustomAttributes (attributeType, inherit);
1200 public override string FullName {
1201 get { return base.FullName; }