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.");
270 // only "Run" is supported by Silverlight
271 // however SMCS requires more than this but runs outside the CoreCLR sandbox
272 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
273 throw new ArgumentException ("access");
276 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
277 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
278 "Argument value {0} is not valid.", (int) access),
282 this.access = (uint)access;
283 flags = (uint) n.Flags;
285 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
286 if (IsSave && (directory == null || directory.Length == 0)) {
287 dir = Directory.GetCurrentDirectory ();
292 /* Set defaults from n */
293 if (n.CultureInfo != null) {
294 culture = n.CultureInfo.Name;
295 versioninfo_culture = n.CultureInfo.Name;
297 Version v = n.Version;
299 version = v.ToString ();
302 if (n.KeyPair != null) {
303 // full keypair is available (for signing)
304 sn = n.KeyPair.StrongName ();
306 // public key is available (for delay-signing)
307 byte[] pk = n.GetPublicKey ();
308 if ((pk != null) && (pk.Length > 0)) {
309 sn = new Mono.Security.StrongName (pk);
314 flags |= (uint) AssemblyNameFlags.PublicKey;
316 this.corlib_internal = corlib_internal;
318 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
320 foreach (byte pkb in sn.PublicKeyToken) {
321 string part = pkb.ToString("x2");
322 this.pktoken[pkti++] = (byte)part[0];
323 this.pktoken[pkti++] = (byte)part[1];
330 public override string CodeBase {
332 throw not_supported ();
336 public override MethodInfo EntryPoint {
342 public override string Location {
344 throw not_supported ();
348 /* This is to keep signature compatibility with MS.NET */
349 public override string ImageRuntimeVersion {
351 return base.ImageRuntimeVersion;
356 public override bool ReflectionOnly {
357 get { return base.ReflectionOnly; }
360 public void AddResourceFile (string name, string fileName)
362 AddResourceFile (name, fileName, ResourceAttributes.Public);
365 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
367 AddResourceFile (name, fileName, attribute, true);
370 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
372 check_name_and_filename (name, fileName, fileNeedsToExists);
374 // Resource files are created/searched under the assembly storage
377 fileName = Path.Combine (dir, fileName);
379 if (resources != null) {
380 MonoResource[] new_r = new MonoResource [resources.Length + 1];
381 System.Array.Copy(resources, new_r, resources.Length);
384 resources = new MonoResource [1];
386 int p = resources.Length - 1;
387 resources [p].name = name;
388 resources [p].filename = fileName;
389 resources [p].attrs = attribute;
392 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
396 throw new InvalidOperationException ("Assembly was already saved.");
398 // required for base Assembly class (so the permissions
399 // can be used even if the assembly isn't saved to disk)
401 _optional = optional;
404 // required to reuse AddDeclarativeSecurity support
405 // already present in the runtime
406 if (required != null) {
407 permissions_minimum = new RefEmitPermissionSet [1];
408 permissions_minimum [0] = new RefEmitPermissionSet (
409 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
411 if (optional != null) {
412 permissions_optional = new RefEmitPermissionSet [1];
413 permissions_optional [0] = new RefEmitPermissionSet (
414 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
416 if (refused != null) {
417 permissions_refused = new RefEmitPermissionSet [1];
418 permissions_refused [0] = new RefEmitPermissionSet (
419 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
424 // Still in use by al.exe
425 internal void EmbedResourceFile (string name, string fileName)
427 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
430 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
432 if (resources != null) {
433 MonoResource[] new_r = new MonoResource [resources.Length + 1];
434 System.Array.Copy(resources, new_r, resources.Length);
437 resources = new MonoResource [1];
439 int p = resources.Length - 1;
440 resources [p].name = name;
441 resources [p].attrs = attribute;
443 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
445 resources [p].data = new byte [len];
446 s.Read (resources [p].data, 0, (int)len);
452 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
454 if (resources != null) {
455 MonoResource[] new_r = new MonoResource [resources.Length + 1];
456 System.Array.Copy(resources, new_r, resources.Length);
459 resources = new MonoResource [1];
461 int p = resources.Length - 1;
462 resources [p].name = name;
463 resources [p].attrs = attribute;
464 resources [p].data = blob;
468 public ModuleBuilder DefineDynamicModule (string name)
470 return DefineDynamicModule (name, name, false, true);
473 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
475 return DefineDynamicModule (name, name, emitSymbolInfo, true);
478 public ModuleBuilder DefineDynamicModule(string name, string fileName)
480 return DefineDynamicModule (name, fileName, false, false);
483 public ModuleBuilder DefineDynamicModule (string name, string fileName,
486 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
489 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
491 check_name_and_filename (name, fileName, false);
494 if (Path.GetExtension (fileName) == String.Empty)
495 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
497 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
499 throw new InvalidOperationException ("Assembly was already saved.");
502 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
504 if ((modules != null) && is_module_only)
505 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
507 if (modules != null) {
508 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
509 System.Array.Copy(modules, new_modules, modules.Length);
510 modules = new_modules;
512 modules = new ModuleBuilder [1];
514 modules [modules.Length - 1] = r;
518 public IResourceWriter DefineResource (string name, string description, string fileName)
520 return DefineResource (name, description, fileName, ResourceAttributes.Public);
523 public IResourceWriter DefineResource (string name, string description,
524 string fileName, ResourceAttributes attribute)
526 IResourceWriter writer;
528 // description seems to be ignored
529 AddResourceFile (name, fileName, attribute, false);
530 writer = new ResourceWriter (fileName);
531 if (resource_writers == null)
532 resource_writers = new ArrayList ();
533 resource_writers.Add (writer);
537 private void AddUnmanagedResource (Win32Resource res) {
538 MemoryStream ms = new MemoryStream ();
541 if (win32_resources != null) {
542 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
543 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
544 win32_resources = new_res;
547 win32_resources = new MonoWin32Resource [1];
549 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
552 [MonoTODO ("Not currently implemenented")]
553 public void DefineUnmanagedResource (byte[] resource)
555 if (resource == null)
556 throw new ArgumentNullException ("resource");
557 if (native_resource != NativeResourceType.None)
558 throw new ArgumentException ("Native resource has already been defined.");
560 // avoid definition of more than one unmanaged resource
561 native_resource = NativeResourceType.Unmanaged;
564 * The format of the argument byte array is not documented
565 * so this method is impossible to implement.
567 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
570 throw new NotImplementedException ();
573 public void DefineUnmanagedResource (string resourceFileName)
575 if (resourceFileName == null)
576 throw new ArgumentNullException ("resourceFileName");
577 if (resourceFileName.Length == 0)
578 throw new ArgumentException ("resourceFileName");
579 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
580 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
581 if (native_resource != NativeResourceType.None)
582 throw new ArgumentException ("Native resource has already been defined.");
584 // avoid definition of more than one unmanaged resource
585 native_resource = NativeResourceType.Unmanaged;
587 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
588 Win32ResFileReader reader = new Win32ResFileReader (fs);
590 foreach (Win32EncodedResource res in reader.ReadResources ()) {
591 if (res.Name.IsName || res.Type.IsName)
592 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
594 AddUnmanagedResource (res);
599 public void DefineVersionInfoResource ()
601 if (native_resource != NativeResourceType.None)
602 throw new ArgumentException ("Native resource has already been defined.");
604 // avoid definition of more than one unmanaged resource
605 native_resource = NativeResourceType.Assembly;
607 version_res = new Win32VersionResource (1, 0, false);
610 public void DefineVersionInfoResource (string product, string productVersion,
611 string company, string copyright, string trademark)
613 if (native_resource != NativeResourceType.None)
614 throw new ArgumentException ("Native resource has already been defined.");
616 // avoid definition of more than one unmanaged resource
617 native_resource = NativeResourceType.Explicit;
620 * We can only create the resource later, when the file name and
621 * the binary version is known.
624 version_res = new Win32VersionResource (1, 0, false);
625 version_res.ProductName = product != null ? product : " ";
626 version_res.ProductVersion = productVersion != null ? productVersion : " ";
627 version_res.CompanyName = company != null ? company : " ";
628 version_res.LegalCopyright = copyright != null ? copyright : " ";
629 version_res.LegalTrademarks = trademark != null ? trademark : " ";
632 private void DefineVersionInfoResourceImpl (string fileName)
634 if (versioninfo_culture != null)
635 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
636 version_res.Version = version == null ? "0.0.0.0" : version;
638 if (cattrs != null) {
639 switch (native_resource) {
640 case NativeResourceType.Assembly:
641 foreach (CustomAttributeBuilder cb in cattrs) {
642 string attrname = cb.Ctor.ReflectedType.FullName;
644 if (attrname == "System.Reflection.AssemblyProductAttribute")
645 version_res.ProductName = cb.string_arg ();
646 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
647 version_res.CompanyName = cb.string_arg ();
648 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
649 version_res.LegalCopyright = cb.string_arg ();
650 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
651 version_res.LegalTrademarks = cb.string_arg ();
652 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
653 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
654 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
655 version_res.FileVersion = cb.string_arg ();
656 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
657 version_res.ProductVersion = cb.string_arg ();
658 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
659 version_res.FileDescription = cb.string_arg ();
660 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
661 version_res.Comments = cb.string_arg ();
664 case NativeResourceType.Explicit:
665 foreach (CustomAttributeBuilder cb in cattrs) {
666 string attrname = cb.Ctor.ReflectedType.FullName;
668 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
669 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
670 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
671 version_res.Comments = cb.string_arg ();
677 version_res.OriginalFilename = fileName;
678 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
680 AddUnmanagedResource (version_res);
683 public ModuleBuilder GetDynamicModule (string name)
686 throw new ArgumentNullException ("name");
687 if (name.Length == 0)
688 throw new ArgumentException ("Empty name is not legal.", "name");
691 for (int i = 0; i < modules.Length; ++i)
692 if (modules [i].name == name)
697 public override Type[] GetExportedTypes ()
699 throw not_supported ();
702 public override FileStream GetFile (string name)
704 throw not_supported ();
707 public override FileStream[] GetFiles(bool getResourceModules) {
708 throw not_supported ();
711 internal override Module[] GetModulesInternal () {
713 return new Module [0];
715 return (Module[])modules.Clone ();
718 internal override Type[] GetTypes (bool exportedOnly) {
720 if (modules != null) {
721 for (int i = 0; i < modules.Length; ++i) {
722 Type[] types = modules [i].GetTypes ();
726 Type[] tmp = new Type [res.Length + types.Length];
727 Array.Copy (res, 0, tmp, 0, res.Length);
728 Array.Copy (types, 0, tmp, res.Length, types.Length);
732 if (loaded_modules != null) {
733 for (int i = 0; i < loaded_modules.Length; ++i) {
734 Type[] types = loaded_modules [i].GetTypes ();
738 Type[] tmp = new Type [res.Length + types.Length];
739 Array.Copy (res, 0, tmp, 0, res.Length);
740 Array.Copy (types, 0, tmp, res.Length, types.Length);
746 List<Exception> exceptions = null;
747 foreach (var type in res) {
748 if (type is TypeBuilder) {
749 if (exceptions == null)
750 exceptions = new List <Exception> ();
751 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
754 if (exceptions != null)
755 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
758 return res == null ? Type.EmptyTypes : res;
761 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
762 throw not_supported ();
765 public override string[] GetManifestResourceNames() {
766 throw not_supported ();
769 public override Stream GetManifestResourceStream(string name) {
770 throw not_supported ();
772 public override Stream GetManifestResourceStream(Type type, string name) {
773 throw not_supported ();
776 internal bool IsSave {
778 return access != (uint)AssemblyBuilderAccess.Run;
782 internal bool IsRun {
784 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
786 || access == (uint)AssemblyBuilderAccess.RunAndCollect
793 internal bool IsCollectible {
795 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
799 internal string AssemblyDir {
806 * Mono extension. If this is set, the assembly can only contain one
807 * module, access should be Save, and the saved image will not contain an
810 internal bool IsModuleOnly {
812 return is_module_only;
815 is_module_only = value;
819 ModuleBuilder manifest_module;
822 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
823 // on an assemblybuilder.
825 internal override Module GetManifestModule () {
826 if (manifest_module == null)
827 manifest_module = DefineDynamicModule ("Default Dynamic Module");
828 return manifest_module;
831 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
833 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
835 this.peKind = portableExecutableKind;
836 this.machine = imageFileMachine;
838 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
839 throw new NotImplementedException (peKind.ToString ());
840 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
841 throw new NotImplementedException (machine.ToString ());
843 if (resource_writers != null) {
844 foreach (IResourceWriter writer in resource_writers) {
850 // Create a main module if not already created
851 ModuleBuilder mainModule = null;
852 if (modules != null) {
853 foreach (ModuleBuilder module in modules)
854 if (module.FullyQualifiedName == assemblyFileName)
857 if (mainModule == null)
858 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
861 mainModule.IsMain = true;
864 * Create a new entry point if the one specified
865 * by the user is in another module.
867 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
869 if (entry_point.GetParameters ().Length == 1)
870 paramTypes = new Type [] { typeof (string) };
872 paramTypes = Type.EmptyTypes;
874 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
875 ILGenerator ilgen = mb.GetILGenerator ();
876 if (paramTypes.Length == 1)
877 ilgen.Emit (OpCodes.Ldarg_0);
878 ilgen.Emit (OpCodes.Tailcall);
879 ilgen.Emit (OpCodes.Call, entry_point);
880 ilgen.Emit (OpCodes.Ret);
885 if (version_res != null)
886 DefineVersionInfoResourceImpl (assemblyFileName);
889 // runtime needs to value to embed it into the assembly
890 public_key = sn.PublicKey;
893 foreach (ModuleBuilder module in modules)
894 if (module != mainModule)
897 // Write out the main module at the end, because it needs to
898 // contain the hash of the other modules
901 if ((sn != null) && (sn.CanSign)) {
902 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
908 public void Save (string assemblyFileName)
910 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
913 public void SetEntryPoint (MethodInfo entryMethod)
915 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
918 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
920 if (entryMethod == null)
921 throw new ArgumentNullException ("entryMethod");
922 if (entryMethod.DeclaringType.Assembly != this)
923 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
925 entry_point = entryMethod;
929 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
931 if (customBuilder == null)
932 throw new ArgumentNullException ("customBuilder");
934 if (cattrs != null) {
935 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
936 cattrs.CopyTo (new_array, 0);
937 new_array [cattrs.Length] = customBuilder;
940 cattrs = new CustomAttributeBuilder [1];
941 cattrs [0] = customBuilder;
946 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
948 throw new ArgumentNullException ("con");
949 if (binaryAttribute == null)
950 throw new ArgumentNullException ("binaryAttribute");
952 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
955 private Exception not_supported () {
956 // Strange message but this is what MS.NET prints...
957 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
960 private void check_name_and_filename (string name, string fileName,
961 bool fileNeedsToExists) {
963 throw new ArgumentNullException ("name");
964 if (fileName == null)
965 throw new ArgumentNullException ("fileName");
966 if (name.Length == 0)
967 throw new ArgumentException ("Empty name is not legal.", "name");
968 if (fileName.Length == 0)
969 throw new ArgumentException ("Empty file name is not legal.", "fileName");
970 if (Path.GetFileName (fileName) != fileName)
971 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
973 // Resource files are created/searched under the assembly storage
975 string fullFileName = fileName;
977 fullFileName = Path.Combine (dir, fileName);
979 if (fileNeedsToExists && !File.Exists (fullFileName))
980 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
982 if (resources != null) {
983 for (int i = 0; i < resources.Length; ++i) {
984 if (resources [i].filename == fullFileName)
985 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
986 if (resources [i].name == name)
987 throw new ArgumentException ("Duplicate name '" + name + "'");
991 if (modules != null) {
992 for (int i = 0; i < modules.Length; ++i) {
993 // Use fileName instead of fullFileName here
994 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
995 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
996 if (modules [i].Name == name)
997 throw new ArgumentException ("Duplicate name '" + name + "'");
1002 private String create_assembly_version (String version) {
1003 String[] parts = version.Split ('.');
1004 int[] ver = new int [4] { 0, 0, 0, 0 };
1006 if ((parts.Length < 0) || (parts.Length > 4))
1007 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1009 for (int i = 0; i < parts.Length; ++i) {
1010 if (parts [i] == "*") {
1011 DateTime now = DateTime.Now;
1014 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1015 if (parts.Length == 3)
1016 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1020 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1022 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1026 ver [i] = Int32.Parse (parts [i]);
1028 catch (FormatException) {
1029 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1034 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1037 private string GetCultureString (string str)
1039 return (str == "neutral" ? String.Empty : str);
1042 internal override AssemblyName UnprotectedGetName ()
1044 AssemblyName an = base.UnprotectedGetName ();
1046 an.SetPublicKey (sn.PublicKey);
1047 an.SetPublicKeyToken (sn.PublicKeyToken);
1052 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1053 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1055 return new MonoGenericClass (gtd, typeArguments);
1058 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1060 throw new NotImplementedException ();
1063 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1065 throw new NotImplementedException ();
1068 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1070 throw new NotImplementedException ();
1073 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1075 throw new NotImplementedException ();
1078 #if NET_4_0 || MOONLIGHT || MOBILE
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; }