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 throw new NotImplementedException ();
474 public ModuleBuilder DefineDynamicModule (string name)
476 return DefineDynamicModule (name, name, false, true);
479 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
481 return DefineDynamicModule (name, name, emitSymbolInfo, true);
484 public ModuleBuilder DefineDynamicModule(string name, string fileName)
486 return DefineDynamicModule (name, fileName, false, false);
489 public ModuleBuilder DefineDynamicModule (string name, string fileName,
492 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
495 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
497 check_name_and_filename (name, fileName, false);
500 if (Path.GetExtension (fileName) == String.Empty)
501 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
503 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
505 throw new InvalidOperationException ("Assembly was already saved.");
508 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
510 if ((modules != null) && is_module_only)
511 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
513 if (modules != null) {
514 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
515 System.Array.Copy(modules, new_modules, modules.Length);
516 modules = new_modules;
518 modules = new ModuleBuilder [1];
520 modules [modules.Length - 1] = r;
524 public IResourceWriter DefineResource (string name, string description, string fileName)
526 return DefineResource (name, description, fileName, ResourceAttributes.Public);
529 public IResourceWriter DefineResource (string name, string description,
530 string fileName, ResourceAttributes attribute)
532 IResourceWriter writer;
534 // description seems to be ignored
535 AddResourceFile (name, fileName, attribute, false);
536 writer = new ResourceWriter (fileName);
537 if (resource_writers == null)
538 resource_writers = new ArrayList ();
539 resource_writers.Add (writer);
543 private void AddUnmanagedResource (Win32Resource res) {
544 MemoryStream ms = new MemoryStream ();
547 if (win32_resources != null) {
548 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
549 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
550 win32_resources = new_res;
553 win32_resources = new MonoWin32Resource [1];
555 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
558 [MonoTODO ("Not currently implemenented")]
559 public void DefineUnmanagedResource (byte[] resource)
561 if (resource == null)
562 throw new ArgumentNullException ("resource");
563 if (native_resource != NativeResourceType.None)
564 throw new ArgumentException ("Native resource has already been defined.");
566 // avoid definition of more than one unmanaged resource
567 native_resource = NativeResourceType.Unmanaged;
570 * The format of the argument byte array is not documented
571 * so this method is impossible to implement.
573 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
576 throw new NotImplementedException ();
579 public void DefineUnmanagedResource (string resourceFileName)
581 if (resourceFileName == null)
582 throw new ArgumentNullException ("resourceFileName");
583 if (resourceFileName.Length == 0)
584 throw new ArgumentException ("resourceFileName");
585 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
586 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
587 if (native_resource != NativeResourceType.None)
588 throw new ArgumentException ("Native resource has already been defined.");
590 // avoid definition of more than one unmanaged resource
591 native_resource = NativeResourceType.Unmanaged;
593 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
594 Win32ResFileReader reader = new Win32ResFileReader (fs);
596 foreach (Win32EncodedResource res in reader.ReadResources ()) {
597 if (res.Name.IsName || res.Type.IsName)
598 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
600 AddUnmanagedResource (res);
605 public void DefineVersionInfoResource ()
607 if (native_resource != NativeResourceType.None)
608 throw new ArgumentException ("Native resource has already been defined.");
610 // avoid definition of more than one unmanaged resource
611 native_resource = NativeResourceType.Assembly;
613 version_res = new Win32VersionResource (1, 0, false);
616 public void DefineVersionInfoResource (string product, string productVersion,
617 string company, string copyright, string trademark)
619 if (native_resource != NativeResourceType.None)
620 throw new ArgumentException ("Native resource has already been defined.");
622 // avoid definition of more than one unmanaged resource
623 native_resource = NativeResourceType.Explicit;
626 * We can only create the resource later, when the file name and
627 * the binary version is known.
630 version_res = new Win32VersionResource (1, 0, false);
631 version_res.ProductName = product != null ? product : " ";
632 version_res.ProductVersion = productVersion != null ? productVersion : " ";
633 version_res.CompanyName = company != null ? company : " ";
634 version_res.LegalCopyright = copyright != null ? copyright : " ";
635 version_res.LegalTrademarks = trademark != null ? trademark : " ";
638 private void DefineVersionInfoResourceImpl (string fileName)
640 if (versioninfo_culture != null)
641 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
642 version_res.Version = version == null ? "0.0.0.0" : version;
644 if (cattrs != null) {
645 switch (native_resource) {
646 case NativeResourceType.Assembly:
647 foreach (CustomAttributeBuilder cb in cattrs) {
648 string attrname = cb.Ctor.ReflectedType.FullName;
650 if (attrname == "System.Reflection.AssemblyProductAttribute")
651 version_res.ProductName = cb.string_arg ();
652 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
653 version_res.CompanyName = cb.string_arg ();
654 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
655 version_res.LegalCopyright = cb.string_arg ();
656 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
657 version_res.LegalTrademarks = cb.string_arg ();
658 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
659 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
660 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
661 version_res.FileVersion = cb.string_arg ();
662 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
663 version_res.ProductVersion = cb.string_arg ();
664 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
665 version_res.FileDescription = cb.string_arg ();
666 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
667 version_res.Comments = cb.string_arg ();
670 case NativeResourceType.Explicit:
671 foreach (CustomAttributeBuilder cb in cattrs) {
672 string attrname = cb.Ctor.ReflectedType.FullName;
674 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
675 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
676 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
677 version_res.Comments = cb.string_arg ();
683 version_res.OriginalFilename = fileName;
684 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
686 AddUnmanagedResource (version_res);
689 public ModuleBuilder GetDynamicModule (string name)
692 throw new ArgumentNullException ("name");
693 if (name.Length == 0)
694 throw new ArgumentException ("Empty name is not legal.", "name");
697 for (int i = 0; i < modules.Length; ++i)
698 if (modules [i].name == name)
703 public override Type[] GetExportedTypes ()
705 throw not_supported ();
708 public override FileStream GetFile (string name)
710 throw not_supported ();
713 public override FileStream[] GetFiles(bool getResourceModules) {
714 throw not_supported ();
717 internal override Module[] GetModulesInternal () {
719 return new Module [0];
721 return (Module[])modules.Clone ();
724 internal override Type[] GetTypes (bool exportedOnly) {
726 if (modules != null) {
727 for (int i = 0; i < modules.Length; ++i) {
728 Type[] types = modules [i].GetTypes ();
732 Type[] tmp = new Type [res.Length + types.Length];
733 Array.Copy (res, 0, tmp, 0, res.Length);
734 Array.Copy (types, 0, tmp, res.Length, types.Length);
738 if (loaded_modules != null) {
739 for (int i = 0; i < loaded_modules.Length; ++i) {
740 Type[] types = loaded_modules [i].GetTypes ();
744 Type[] tmp = new Type [res.Length + types.Length];
745 Array.Copy (res, 0, tmp, 0, res.Length);
746 Array.Copy (types, 0, tmp, res.Length, types.Length);
752 List<Exception> exceptions = null;
753 foreach (var type in res) {
754 if (type is TypeBuilder) {
755 if (exceptions == null)
756 exceptions = new List <Exception> ();
757 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
760 if (exceptions != null)
761 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
764 return res == null ? Type.EmptyTypes : res;
767 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
768 throw not_supported ();
771 public override string[] GetManifestResourceNames() {
772 throw not_supported ();
775 public override Stream GetManifestResourceStream(string name) {
776 throw not_supported ();
778 public override Stream GetManifestResourceStream(Type type, string name) {
779 throw not_supported ();
782 internal bool IsSave {
784 return access != (uint)AssemblyBuilderAccess.Run;
788 internal bool IsRun {
790 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
791 || access == (uint)AssemblyBuilderAccess.RunAndCollect
797 internal bool IsCollectible {
799 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
803 internal string AssemblyDir {
810 * Mono extension. If this is set, the assembly can only contain one
811 * module, access should be Save, and the saved image will not contain an
814 internal bool IsModuleOnly {
816 return is_module_only;
819 is_module_only = value;
823 ModuleBuilder manifest_module;
826 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
827 // on an assemblybuilder.
829 internal override Module GetManifestModule () {
830 if (manifest_module == null)
831 manifest_module = DefineDynamicModule ("Default Dynamic Module");
832 return manifest_module;
835 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
837 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
839 this.peKind = portableExecutableKind;
840 this.machine = imageFileMachine;
842 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
843 throw new NotImplementedException (peKind.ToString ());
844 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
845 throw new NotImplementedException (machine.ToString ());
847 if (resource_writers != null) {
848 foreach (IResourceWriter writer in resource_writers) {
854 // Create a main module if not already created
855 ModuleBuilder mainModule = null;
856 if (modules != null) {
857 foreach (ModuleBuilder module in modules)
858 if (module.FullyQualifiedName == assemblyFileName)
861 if (mainModule == null)
862 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
865 mainModule.IsMain = true;
868 * Create a new entry point if the one specified
869 * by the user is in another module.
871 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
873 if (entry_point.GetParametersCount () == 1)
874 paramTypes = new Type [] { typeof (string) };
876 paramTypes = Type.EmptyTypes;
878 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
879 ILGenerator ilgen = mb.GetILGenerator ();
880 if (paramTypes.Length == 1)
881 ilgen.Emit (OpCodes.Ldarg_0);
882 ilgen.Emit (OpCodes.Tailcall);
883 ilgen.Emit (OpCodes.Call, entry_point);
884 ilgen.Emit (OpCodes.Ret);
889 if (version_res != null)
890 DefineVersionInfoResourceImpl (assemblyFileName);
893 // runtime needs to value to embed it into the assembly
894 public_key = sn.PublicKey;
897 foreach (ModuleBuilder module in modules)
898 if (module != mainModule)
901 // Write out the main module at the end, because it needs to
902 // contain the hash of the other modules
905 if ((sn != null) && (sn.CanSign)) {
906 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
912 public void Save (string assemblyFileName)
914 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
917 public void SetEntryPoint (MethodInfo entryMethod)
919 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
922 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
924 if (entryMethod == null)
925 throw new ArgumentNullException ("entryMethod");
926 if (entryMethod.DeclaringType.Assembly != this)
927 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
929 entry_point = entryMethod;
933 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
935 if (customBuilder == null)
936 throw new ArgumentNullException ("customBuilder");
938 if (cattrs != null) {
939 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
940 cattrs.CopyTo (new_array, 0);
941 new_array [cattrs.Length] = customBuilder;
944 cattrs = new CustomAttributeBuilder [1];
945 cattrs [0] = customBuilder;
950 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
952 throw new ArgumentNullException ("con");
953 if (binaryAttribute == null)
954 throw new ArgumentNullException ("binaryAttribute");
956 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
959 private Exception not_supported () {
960 // Strange message but this is what MS.NET prints...
961 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
964 private void check_name_and_filename (string name, string fileName,
965 bool fileNeedsToExists) {
967 throw new ArgumentNullException ("name");
968 if (fileName == null)
969 throw new ArgumentNullException ("fileName");
970 if (name.Length == 0)
971 throw new ArgumentException ("Empty name is not legal.", "name");
972 if (fileName.Length == 0)
973 throw new ArgumentException ("Empty file name is not legal.", "fileName");
974 if (Path.GetFileName (fileName) != fileName)
975 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
977 // Resource files are created/searched under the assembly storage
979 string fullFileName = fileName;
981 fullFileName = Path.Combine (dir, fileName);
983 if (fileNeedsToExists && !File.Exists (fullFileName))
984 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
986 if (resources != null) {
987 for (int i = 0; i < resources.Length; ++i) {
988 if (resources [i].filename == fullFileName)
989 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
990 if (resources [i].name == name)
991 throw new ArgumentException ("Duplicate name '" + name + "'");
995 if (modules != null) {
996 for (int i = 0; i < modules.Length; ++i) {
997 // Use fileName instead of fullFileName here
998 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
999 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1000 if (modules [i].Name == name)
1001 throw new ArgumentException ("Duplicate name '" + name + "'");
1006 private String create_assembly_version (String version) {
1007 String[] parts = version.Split ('.');
1008 int[] ver = new int [4] { 0, 0, 0, 0 };
1010 if ((parts.Length < 0) || (parts.Length > 4))
1011 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1013 for (int i = 0; i < parts.Length; ++i) {
1014 if (parts [i] == "*") {
1015 DateTime now = DateTime.Now;
1018 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1019 if (parts.Length == 3)
1020 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1024 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1026 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1030 ver [i] = Int32.Parse (parts [i]);
1032 catch (FormatException) {
1033 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1038 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1041 private string GetCultureString (string str)
1043 return (str == "neutral" ? String.Empty : str);
1046 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1047 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1049 return new TypeBuilderInstantiation (gtd, typeArguments);
1052 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1054 throw new NotImplementedException ();
1057 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1059 throw new NotImplementedException ();
1062 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1064 throw new NotImplementedException ();
1067 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1069 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 var aname = AssemblyName.Create (this, false);
1125 aname.SetPublicKey (sn.PublicKey);
1126 aname.SetPublicKeyToken (sn.PublicKeyToken);
1132 [MonoTODO ("This always returns an empty array")]
1133 public override AssemblyName[] GetReferencedAssemblies () {
1134 return GetReferencedAssemblies (this);
1137 public override Module[] GetLoadedModules (bool getResourceModules)
1139 return GetModules (getResourceModules);
1142 //FIXME MS has issues loading satelite assemblies from SRE
1143 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1145 return GetSatelliteAssembly (culture, null, true);
1148 //FIXME MS has issues loading satelite assemblies from SRE
1149 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1151 return GetSatelliteAssembly (culture, version, true);
1154 public override Module ManifestModule {
1156 return GetManifestModule ();
1160 public override bool GlobalAssemblyCache {
1166 public override bool IsDynamic {
1167 get { return true; }
1170 public override bool Equals (object obj)
1172 return base.Equals (obj);
1175 public override int GetHashCode ()
1177 return base.GetHashCode ();
1180 public override bool IsDefined (Type attributeType, bool inherit)
1182 return base.IsDefined (attributeType, inherit);
1185 public override object[] GetCustomAttributes (bool inherit)
1187 return base.GetCustomAttributes (inherit);
1190 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1192 return base.GetCustomAttributes (attributeType, inherit);
1195 public override string FullName {
1196 get { return base.FullName; }