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;
462 public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access)
465 throw new ArgumentNullException ("name");
467 return new AssemblyBuilder (name, null, access, false);
471 public ModuleBuilder DefineDynamicModule (string name)
473 return DefineDynamicModule (name, name, false, true);
476 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
478 return DefineDynamicModule (name, name, emitSymbolInfo, true);
481 public ModuleBuilder DefineDynamicModule(string name, string fileName)
483 return DefineDynamicModule (name, fileName, false, false);
486 public ModuleBuilder DefineDynamicModule (string name, string fileName,
489 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
492 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
494 check_name_and_filename (name, fileName, false);
497 if (Path.GetExtension (fileName) == String.Empty)
498 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
500 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
502 throw new InvalidOperationException ("Assembly was already saved.");
505 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
507 if ((modules != null) && is_module_only)
508 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
510 if (modules != null) {
511 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
512 System.Array.Copy(modules, new_modules, modules.Length);
513 modules = new_modules;
515 modules = new ModuleBuilder [1];
517 modules [modules.Length - 1] = r;
521 public IResourceWriter DefineResource (string name, string description, string fileName)
523 return DefineResource (name, description, fileName, ResourceAttributes.Public);
526 public IResourceWriter DefineResource (string name, string description,
527 string fileName, ResourceAttributes attribute)
529 IResourceWriter writer;
531 // description seems to be ignored
532 AddResourceFile (name, fileName, attribute, false);
533 writer = new ResourceWriter (fileName);
534 if (resource_writers == null)
535 resource_writers = new ArrayList ();
536 resource_writers.Add (writer);
540 private void AddUnmanagedResource (Win32Resource res) {
541 MemoryStream ms = new MemoryStream ();
544 if (win32_resources != null) {
545 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
546 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
547 win32_resources = new_res;
550 win32_resources = new MonoWin32Resource [1];
552 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
555 [MonoTODO ("Not currently implemenented")]
556 public void DefineUnmanagedResource (byte[] resource)
558 if (resource == null)
559 throw new ArgumentNullException ("resource");
560 if (native_resource != NativeResourceType.None)
561 throw new ArgumentException ("Native resource has already been defined.");
563 // avoid definition of more than one unmanaged resource
564 native_resource = NativeResourceType.Unmanaged;
567 * The format of the argument byte array is not documented
568 * so this method is impossible to implement.
570 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
573 throw new NotImplementedException ();
576 public void DefineUnmanagedResource (string resourceFileName)
578 if (resourceFileName == null)
579 throw new ArgumentNullException ("resourceFileName");
580 if (resourceFileName.Length == 0)
581 throw new ArgumentException ("resourceFileName");
582 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
583 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
584 if (native_resource != NativeResourceType.None)
585 throw new ArgumentException ("Native resource has already been defined.");
587 // avoid definition of more than one unmanaged resource
588 native_resource = NativeResourceType.Unmanaged;
590 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
591 Win32ResFileReader reader = new Win32ResFileReader (fs);
593 foreach (Win32EncodedResource res in reader.ReadResources ()) {
594 if (res.Name.IsName || res.Type.IsName)
595 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
597 AddUnmanagedResource (res);
602 public void DefineVersionInfoResource ()
604 if (native_resource != NativeResourceType.None)
605 throw new ArgumentException ("Native resource has already been defined.");
607 // avoid definition of more than one unmanaged resource
608 native_resource = NativeResourceType.Assembly;
610 version_res = new Win32VersionResource (1, 0, false);
613 public void DefineVersionInfoResource (string product, string productVersion,
614 string company, string copyright, string trademark)
616 if (native_resource != NativeResourceType.None)
617 throw new ArgumentException ("Native resource has already been defined.");
619 // avoid definition of more than one unmanaged resource
620 native_resource = NativeResourceType.Explicit;
623 * We can only create the resource later, when the file name and
624 * the binary version is known.
627 version_res = new Win32VersionResource (1, 0, false);
628 version_res.ProductName = product != null ? product : " ";
629 version_res.ProductVersion = productVersion != null ? productVersion : " ";
630 version_res.CompanyName = company != null ? company : " ";
631 version_res.LegalCopyright = copyright != null ? copyright : " ";
632 version_res.LegalTrademarks = trademark != null ? trademark : " ";
635 private void DefineVersionInfoResourceImpl (string fileName)
637 if (versioninfo_culture != null)
638 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
639 version_res.Version = version == null ? "0.0.0.0" : version;
641 if (cattrs != null) {
642 switch (native_resource) {
643 case NativeResourceType.Assembly:
644 foreach (CustomAttributeBuilder cb in cattrs) {
645 string attrname = cb.Ctor.ReflectedType.FullName;
647 if (attrname == "System.Reflection.AssemblyProductAttribute")
648 version_res.ProductName = cb.string_arg ();
649 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
650 version_res.CompanyName = cb.string_arg ();
651 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
652 version_res.LegalCopyright = cb.string_arg ();
653 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
654 version_res.LegalTrademarks = cb.string_arg ();
655 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
656 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
657 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
658 version_res.FileVersion = cb.string_arg ();
659 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
660 version_res.ProductVersion = cb.string_arg ();
661 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
662 version_res.FileDescription = cb.string_arg ();
663 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
664 version_res.Comments = cb.string_arg ();
667 case NativeResourceType.Explicit:
668 foreach (CustomAttributeBuilder cb in cattrs) {
669 string attrname = cb.Ctor.ReflectedType.FullName;
671 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
672 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
673 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
674 version_res.Comments = cb.string_arg ();
680 version_res.OriginalFilename = fileName;
681 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
683 AddUnmanagedResource (version_res);
686 public ModuleBuilder GetDynamicModule (string name)
689 throw new ArgumentNullException ("name");
690 if (name.Length == 0)
691 throw new ArgumentException ("Empty name is not legal.", "name");
694 for (int i = 0; i < modules.Length; ++i)
695 if (modules [i].name == name)
700 public override Type[] GetExportedTypes ()
702 throw not_supported ();
705 public override FileStream GetFile (string name)
707 throw not_supported ();
710 public override FileStream[] GetFiles(bool getResourceModules) {
711 throw not_supported ();
714 internal override Module[] GetModulesInternal () {
716 return new Module [0];
718 return (Module[])modules.Clone ();
721 internal override Type[] GetTypes (bool exportedOnly) {
723 if (modules != null) {
724 for (int i = 0; i < modules.Length; ++i) {
725 Type[] types = modules [i].GetTypes ();
729 Type[] tmp = new Type [res.Length + types.Length];
730 Array.Copy (res, 0, tmp, 0, res.Length);
731 Array.Copy (types, 0, tmp, res.Length, types.Length);
735 if (loaded_modules != null) {
736 for (int i = 0; i < loaded_modules.Length; ++i) {
737 Type[] types = loaded_modules [i].GetTypes ();
741 Type[] tmp = new Type [res.Length + types.Length];
742 Array.Copy (res, 0, tmp, 0, res.Length);
743 Array.Copy (types, 0, tmp, res.Length, types.Length);
749 List<Exception> exceptions = null;
750 foreach (var type in res) {
751 if (type is TypeBuilder) {
752 if (exceptions == null)
753 exceptions = new List <Exception> ();
754 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
757 if (exceptions != null)
758 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
761 return res == null ? Type.EmptyTypes : res;
764 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
765 throw not_supported ();
768 public override string[] GetManifestResourceNames() {
769 throw not_supported ();
772 public override Stream GetManifestResourceStream(string name) {
773 throw not_supported ();
775 public override Stream GetManifestResourceStream(Type type, string name) {
776 throw not_supported ();
779 internal bool IsSave {
781 return access != (uint)AssemblyBuilderAccess.Run;
785 internal bool IsRun {
787 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
788 || access == (uint)AssemblyBuilderAccess.RunAndCollect
794 internal bool IsCollectible {
796 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
800 internal string AssemblyDir {
807 * Mono extension. If this is set, the assembly can only contain one
808 * module, access should be Save, and the saved image will not contain an
811 internal bool IsModuleOnly {
813 return is_module_only;
816 is_module_only = value;
820 ModuleBuilder manifest_module;
823 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
824 // on an assemblybuilder.
826 internal override Module GetManifestModule () {
827 if (manifest_module == null)
828 manifest_module = DefineDynamicModule ("Default Dynamic Module");
829 return manifest_module;
832 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
834 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
836 this.peKind = portableExecutableKind;
837 this.machine = imageFileMachine;
839 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
840 throw new NotImplementedException (peKind.ToString ());
841 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
842 throw new NotImplementedException (machine.ToString ());
844 if (resource_writers != null) {
845 foreach (IResourceWriter writer in resource_writers) {
851 // Create a main module if not already created
852 ModuleBuilder mainModule = null;
853 if (modules != null) {
854 foreach (ModuleBuilder module in modules)
855 if (module.FullyQualifiedName == assemblyFileName)
858 if (mainModule == null)
859 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
862 mainModule.IsMain = true;
865 * Create a new entry point if the one specified
866 * by the user is in another module.
868 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
870 if (entry_point.GetParametersCount () == 1)
871 paramTypes = new Type [] { typeof (string) };
873 paramTypes = Type.EmptyTypes;
875 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
876 ILGenerator ilgen = mb.GetILGenerator ();
877 if (paramTypes.Length == 1)
878 ilgen.Emit (OpCodes.Ldarg_0);
879 ilgen.Emit (OpCodes.Tailcall);
880 ilgen.Emit (OpCodes.Call, entry_point);
881 ilgen.Emit (OpCodes.Ret);
886 if (version_res != null)
887 DefineVersionInfoResourceImpl (assemblyFileName);
890 // runtime needs to value to embed it into the assembly
891 public_key = sn.PublicKey;
894 foreach (ModuleBuilder module in modules)
895 if (module != mainModule)
898 // Write out the main module at the end, because it needs to
899 // contain the hash of the other modules
902 if ((sn != null) && (sn.CanSign)) {
903 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
909 public void Save (string assemblyFileName)
911 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
914 public void SetEntryPoint (MethodInfo entryMethod)
916 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
919 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
921 if (entryMethod == null)
922 throw new ArgumentNullException ("entryMethod");
923 if (entryMethod.DeclaringType.Assembly != this)
924 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
926 entry_point = entryMethod;
930 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
932 if (customBuilder == null)
933 throw new ArgumentNullException ("customBuilder");
935 if (cattrs != null) {
936 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
937 cattrs.CopyTo (new_array, 0);
938 new_array [cattrs.Length] = customBuilder;
941 cattrs = new CustomAttributeBuilder [1];
942 cattrs [0] = customBuilder;
947 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
949 throw new ArgumentNullException ("con");
950 if (binaryAttribute == null)
951 throw new ArgumentNullException ("binaryAttribute");
953 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
956 private Exception not_supported () {
957 // Strange message but this is what MS.NET prints...
958 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
961 private void check_name_and_filename (string name, string fileName,
962 bool fileNeedsToExists) {
964 throw new ArgumentNullException ("name");
965 if (fileName == null)
966 throw new ArgumentNullException ("fileName");
967 if (name.Length == 0)
968 throw new ArgumentException ("Empty name is not legal.", "name");
969 if (fileName.Length == 0)
970 throw new ArgumentException ("Empty file name is not legal.", "fileName");
971 if (Path.GetFileName (fileName) != fileName)
972 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
974 // Resource files are created/searched under the assembly storage
976 string fullFileName = fileName;
978 fullFileName = Path.Combine (dir, fileName);
980 if (fileNeedsToExists && !File.Exists (fullFileName))
981 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
983 if (resources != null) {
984 for (int i = 0; i < resources.Length; ++i) {
985 if (resources [i].filename == fullFileName)
986 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
987 if (resources [i].name == name)
988 throw new ArgumentException ("Duplicate name '" + name + "'");
992 if (modules != null) {
993 for (int i = 0; i < modules.Length; ++i) {
994 // Use fileName instead of fullFileName here
995 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
996 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
997 if (modules [i].Name == name)
998 throw new ArgumentException ("Duplicate name '" + name + "'");
1003 private String create_assembly_version (String version) {
1004 String[] parts = version.Split ('.');
1005 int[] ver = new int [4] { 0, 0, 0, 0 };
1007 if ((parts.Length < 0) || (parts.Length > 4))
1008 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1010 for (int i = 0; i < parts.Length; ++i) {
1011 if (parts [i] == "*") {
1012 DateTime now = DateTime.Now;
1015 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1016 if (parts.Length == 3)
1017 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1021 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1023 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1027 ver [i] = Int32.Parse (parts [i]);
1029 catch (FormatException) {
1030 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1035 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1038 private string GetCultureString (string str)
1040 return (str == "neutral" ? String.Empty : str);
1043 internal override AssemblyName UnprotectedGetName ()
1045 AssemblyName an = base.UnprotectedGetName ();
1047 an.SetPublicKey (sn.PublicKey);
1048 an.SetPublicKeyToken (sn.PublicKeyToken);
1053 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1054 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1056 return new MonoGenericClass (gtd, typeArguments);
1059 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1061 throw new NotImplementedException ();
1064 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1066 throw new NotImplementedException ();
1069 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1071 throw new NotImplementedException ();
1074 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1076 throw new NotImplementedException ();
1079 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1082 throw new ArgumentNullException (name);
1083 if (name.Length == 0)
1084 throw new ArgumentException ("name", "Name cannot be empty");
1086 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1087 if (res is TypeBuilder) {
1089 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1095 public override Module GetModule (String name)
1098 throw new ArgumentNullException ("name");
1099 if (name.Length == 0)
1100 throw new ArgumentException ("Name can't be empty");
1102 if (modules == null)
1105 foreach (Module module in modules) {
1106 if (module.ScopeName == name)
1113 public override Module[] GetModules (bool getResourceModules)
1115 Module[] modules = GetModulesInternal ();
1117 if (!getResourceModules) {
1118 var result = new List<Module> (modules.Length);
1119 foreach (Module m in modules)
1120 if (!m.IsResource ())
1122 return result.ToArray ();
1127 public override AssemblyName GetName (bool copiedName)
1129 return base.GetName (copiedName);
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; }