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.
34 using System.Reflection;
35 using System.Resources;
37 using System.Security.Policy;
38 using System.Runtime.Serialization;
39 using System.Globalization;
40 using System.Runtime.CompilerServices;
41 using System.Collections;
42 using System.Collections.Generic;
43 using System.Runtime.InteropServices;
44 using System.Security;
45 using System.Security.Cryptography;
46 using System.Security.Permissions;
49 using Mono.Security.Cryptography;
51 namespace System.Reflection.Emit
53 internal enum NativeResourceType
61 internal struct RefEmitPermissionSet {
62 public SecurityAction action;
65 public RefEmitPermissionSet (SecurityAction action, string pset) {
71 internal struct MonoResource {
72 #pragma warning disable 649
75 public string filename;
76 public ResourceAttributes attrs;
79 #pragma warning restore 649
82 internal struct MonoWin32Resource {
88 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
89 this.res_type = res_type;
91 this.lang_id = lang_id;
96 internal class GenericInstanceKey {
101 internal GenericInstanceKey (Type gtd, Type[] args)
106 hash_code = gtd.GetHashCode ();
107 for (int i = 0; i < args.Length; ++i)
108 hash_code ^= args [i].GetHashCode ();
111 static bool IsBoundedVector (Type type) {
112 ArrayType at = type as ArrayType;
114 return at.GetEffectiveRank () == 1;
115 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
118 static bool TypeEquals (Type a, Type b) {
122 if (a.HasElementType) {
123 if (!b.HasElementType)
125 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
130 int rank = a.GetArrayRank ();
131 if (rank != b.GetArrayRank ())
133 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
135 } else if (a.IsByRef) {
138 } else if (a.IsPointer) {
145 if (a.IsGenericType) {
146 if (!b.IsGenericType)
148 if (a.IsGenericParameter)
150 if (a.IsGenericParameter) //previous test should have caught it
153 if (a.IsGenericTypeDefinition) {
154 if (!b.IsGenericTypeDefinition)
157 if (b.IsGenericTypeDefinition)
159 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
162 Type[] argsA = a.GetGenericArguments ();
163 Type[] argsB = b.GetGenericArguments ();
164 for (int i = 0; i < argsA.Length; ++i) {
165 if (!TypeEquals (argsA [i], argsB [i]))
172 Now only non-generic, non compound types are left. To properly deal with user
173 types we would have to call UnderlyingSystemType, but we let them have their
174 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
175 depend on proper UT canonicalization.
180 public override bool Equals (object obj)
182 GenericInstanceKey other = obj as GenericInstanceKey;
185 if (gtd != other.gtd)
187 for (int i = 0; i < args.Length; ++i) {
189 Type b = other.args [i];
191 We must cannonicalize as much as we can. Using equals means that some resulting types
192 won't have the exact same types as the argument ones.
193 For example, flyweight types used array, pointer and byref will should this behavior.
194 MCS seens to be resilient to this problem so hopefully this won't show up.
196 if (a != b && !a.Equals (b))
202 public override int GetHashCode ()
210 [ComDefaultInterface (typeof (_AssemblyBuilder))]
211 [ClassInterface (ClassInterfaceType.None)]
212 [StructLayout (LayoutKind.Sequential)]
213 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
214 #pragma warning disable 169, 414, 649
215 #region Sync with object-internals.h
216 private UIntPtr dynamic_assembly; /* GC-tracked */
217 private MethodInfo entry_point;
218 private ModuleBuilder[] modules;
221 private CustomAttributeBuilder[] cattrs;
222 private MonoResource[] resources;
228 PEFileKinds pekind = PEFileKinds.Dll;
231 Module[] loaded_modules;
232 MonoWin32Resource[] win32_resources;
233 private RefEmitPermissionSet[] permissions_minimum;
234 private RefEmitPermissionSet[] permissions_optional;
235 private RefEmitPermissionSet[] permissions_refused;
236 PortableExecutableKinds peKind;
237 ImageFileMachine machine;
238 bool corlib_internal;
239 Type[] type_forwarders;
242 #pragma warning restore 169, 414, 649
244 internal Type corlib_object_type = typeof (System.Object);
245 internal Type corlib_value_type = typeof (System.ValueType);
246 internal Type corlib_enum_type = typeof (System.Enum);
247 internal Type corlib_void_type = typeof (void);
248 ArrayList resource_writers = null;
249 Win32VersionResource version_res;
252 private Mono.Security.StrongName sn;
253 NativeResourceType native_resource;
254 string versioninfo_culture;
256 [MethodImplAttribute(MethodImplOptions.InternalCall)]
257 private static extern void basic_init (AssemblyBuilder ab);
259 /* Keep this in sync with codegen.cs in mcs */
260 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
262 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
264 /* This is obsolete now, as mcs doesn't use SRE any more */
265 if ((access & COMPILER_ACCESS) != 0)
266 throw new NotImplementedException ("COMPILER_ACCESS is no longer supperted, use a newer mcs.");
269 // only "Run" is supported by Silverlight
270 // however SMCS requires more than this but runs outside the CoreCLR sandbox
271 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
272 throw new ArgumentException ("access");
275 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
276 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
277 "Argument value {0} is not valid.", (int) access),
281 this.access = (uint)access;
282 flags = (uint) n.Flags;
284 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
285 if (IsSave && (directory == null || directory.Length == 0)) {
286 dir = Directory.GetCurrentDirectory ();
291 /* Set defaults from n */
292 if (n.CultureInfo != null) {
293 culture = n.CultureInfo.Name;
294 versioninfo_culture = n.CultureInfo.Name;
296 Version v = n.Version;
298 version = v.ToString ();
301 if (n.KeyPair != null) {
302 // full keypair is available (for signing)
303 sn = n.KeyPair.StrongName ();
305 // public key is available (for delay-signing)
306 byte[] pk = n.GetPublicKey ();
307 if ((pk != null) && (pk.Length > 0)) {
308 sn = new Mono.Security.StrongName (pk);
313 flags |= (uint) AssemblyNameFlags.PublicKey;
315 this.corlib_internal = corlib_internal;
317 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
319 foreach (byte pkb in sn.PublicKeyToken) {
320 string part = pkb.ToString("x2");
321 this.pktoken[pkti++] = (byte)part[0];
322 this.pktoken[pkti++] = (byte)part[1];
329 public override string CodeBase {
331 throw not_supported ();
335 public override MethodInfo EntryPoint {
341 public override string Location {
343 throw not_supported ();
347 /* This is to keep signature compatibility with MS.NET */
348 public override string ImageRuntimeVersion {
350 return base.ImageRuntimeVersion;
355 public override bool ReflectionOnly {
356 get { return base.ReflectionOnly; }
359 public void AddResourceFile (string name, string fileName)
361 AddResourceFile (name, fileName, ResourceAttributes.Public);
364 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
366 AddResourceFile (name, fileName, attribute, true);
369 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
371 check_name_and_filename (name, fileName, fileNeedsToExists);
373 // Resource files are created/searched under the assembly storage
376 fileName = Path.Combine (dir, fileName);
378 if (resources != null) {
379 MonoResource[] new_r = new MonoResource [resources.Length + 1];
380 System.Array.Copy(resources, new_r, resources.Length);
383 resources = new MonoResource [1];
385 int p = resources.Length - 1;
386 resources [p].name = name;
387 resources [p].filename = fileName;
388 resources [p].attrs = attribute;
391 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
395 throw new InvalidOperationException ("Assembly was already saved.");
397 // required for base Assembly class (so the permissions
398 // can be used even if the assembly isn't saved to disk)
400 _optional = optional;
403 // required to reuse AddDeclarativeSecurity support
404 // already present in the runtime
405 if (required != null) {
406 permissions_minimum = new RefEmitPermissionSet [1];
407 permissions_minimum [0] = new RefEmitPermissionSet (
408 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
410 if (optional != null) {
411 permissions_optional = new RefEmitPermissionSet [1];
412 permissions_optional [0] = new RefEmitPermissionSet (
413 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
415 if (refused != null) {
416 permissions_refused = new RefEmitPermissionSet [1];
417 permissions_refused [0] = new RefEmitPermissionSet (
418 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
423 // Still in use by al.exe
424 internal void EmbedResourceFile (string name, string fileName)
426 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
429 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
431 if (resources != null) {
432 MonoResource[] new_r = new MonoResource [resources.Length + 1];
433 System.Array.Copy(resources, new_r, resources.Length);
436 resources = new MonoResource [1];
438 int p = resources.Length - 1;
439 resources [p].name = name;
440 resources [p].attrs = attribute;
442 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
444 resources [p].data = new byte [len];
445 s.Read (resources [p].data, 0, (int)len);
451 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
453 if (resources != null) {
454 MonoResource[] new_r = new MonoResource [resources.Length + 1];
455 System.Array.Copy(resources, new_r, resources.Length);
458 resources = new MonoResource [1];
460 int p = resources.Length - 1;
461 resources [p].name = name;
462 resources [p].attrs = attribute;
463 resources [p].data = blob;
467 public ModuleBuilder DefineDynamicModule (string name)
469 return DefineDynamicModule (name, name, false, true);
472 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
474 return DefineDynamicModule (name, name, emitSymbolInfo, true);
477 public ModuleBuilder DefineDynamicModule(string name, string fileName)
479 return DefineDynamicModule (name, fileName, false, false);
482 public ModuleBuilder DefineDynamicModule (string name, string fileName,
485 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
488 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
490 check_name_and_filename (name, fileName, false);
493 if (Path.GetExtension (fileName) == String.Empty)
494 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
496 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
498 throw new InvalidOperationException ("Assembly was already saved.");
501 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
503 if ((modules != null) && is_module_only)
504 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
506 if (modules != null) {
507 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
508 System.Array.Copy(modules, new_modules, modules.Length);
509 modules = new_modules;
511 modules = new ModuleBuilder [1];
513 modules [modules.Length - 1] = r;
517 public IResourceWriter DefineResource (string name, string description, string fileName)
519 return DefineResource (name, description, fileName, ResourceAttributes.Public);
522 public IResourceWriter DefineResource (string name, string description,
523 string fileName, ResourceAttributes attribute)
525 IResourceWriter writer;
527 // description seems to be ignored
528 AddResourceFile (name, fileName, attribute, false);
529 writer = new ResourceWriter (fileName);
530 if (resource_writers == null)
531 resource_writers = new ArrayList ();
532 resource_writers.Add (writer);
536 private void AddUnmanagedResource (Win32Resource res) {
537 MemoryStream ms = new MemoryStream ();
540 if (win32_resources != null) {
541 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
542 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
543 win32_resources = new_res;
546 win32_resources = new MonoWin32Resource [1];
548 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
551 [MonoTODO ("Not currently implemenented")]
552 public void DefineUnmanagedResource (byte[] resource)
554 if (resource == null)
555 throw new ArgumentNullException ("resource");
556 if (native_resource != NativeResourceType.None)
557 throw new ArgumentException ("Native resource has already been defined.");
559 // avoid definition of more than one unmanaged resource
560 native_resource = NativeResourceType.Unmanaged;
563 * The format of the argument byte array is not documented
564 * so this method is impossible to implement.
566 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
569 throw new NotImplementedException ();
572 public void DefineUnmanagedResource (string resourceFileName)
574 if (resourceFileName == null)
575 throw new ArgumentNullException ("resourceFileName");
576 if (resourceFileName.Length == 0)
577 throw new ArgumentException ("resourceFileName");
578 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
579 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
580 if (native_resource != NativeResourceType.None)
581 throw new ArgumentException ("Native resource has already been defined.");
583 // avoid definition of more than one unmanaged resource
584 native_resource = NativeResourceType.Unmanaged;
586 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
587 Win32ResFileReader reader = new Win32ResFileReader (fs);
589 foreach (Win32EncodedResource res in reader.ReadResources ()) {
590 if (res.Name.IsName || res.Type.IsName)
591 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
593 AddUnmanagedResource (res);
598 public void DefineVersionInfoResource ()
600 if (native_resource != NativeResourceType.None)
601 throw new ArgumentException ("Native resource has already been defined.");
603 // avoid definition of more than one unmanaged resource
604 native_resource = NativeResourceType.Assembly;
606 version_res = new Win32VersionResource (1, 0, false);
609 public void DefineVersionInfoResource (string product, string productVersion,
610 string company, string copyright, string trademark)
612 if (native_resource != NativeResourceType.None)
613 throw new ArgumentException ("Native resource has already been defined.");
615 // avoid definition of more than one unmanaged resource
616 native_resource = NativeResourceType.Explicit;
619 * We can only create the resource later, when the file name and
620 * the binary version is known.
623 version_res = new Win32VersionResource (1, 0, false);
624 version_res.ProductName = product != null ? product : " ";
625 version_res.ProductVersion = productVersion != null ? productVersion : " ";
626 version_res.CompanyName = company != null ? company : " ";
627 version_res.LegalCopyright = copyright != null ? copyright : " ";
628 version_res.LegalTrademarks = trademark != null ? trademark : " ";
631 private void DefineVersionInfoResourceImpl (string fileName)
633 if (versioninfo_culture != null)
634 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
635 version_res.Version = version == null ? "0.0.0.0" : version;
637 if (cattrs != null) {
638 switch (native_resource) {
639 case NativeResourceType.Assembly:
640 foreach (CustomAttributeBuilder cb in cattrs) {
641 string attrname = cb.Ctor.ReflectedType.FullName;
643 if (attrname == "System.Reflection.AssemblyProductAttribute")
644 version_res.ProductName = cb.string_arg ();
645 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
646 version_res.CompanyName = cb.string_arg ();
647 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
648 version_res.LegalCopyright = cb.string_arg ();
649 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
650 version_res.LegalTrademarks = cb.string_arg ();
651 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
652 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
653 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
654 version_res.FileVersion = cb.string_arg ();
655 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
656 version_res.ProductVersion = cb.string_arg ();
657 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
658 version_res.FileDescription = cb.string_arg ();
659 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
660 version_res.Comments = cb.string_arg ();
663 case NativeResourceType.Explicit:
664 foreach (CustomAttributeBuilder cb in cattrs) {
665 string attrname = cb.Ctor.ReflectedType.FullName;
667 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
668 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
669 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
670 version_res.Comments = cb.string_arg ();
676 version_res.OriginalFilename = fileName;
677 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
679 AddUnmanagedResource (version_res);
682 public ModuleBuilder GetDynamicModule (string name)
685 throw new ArgumentNullException ("name");
686 if (name.Length == 0)
687 throw new ArgumentException ("Empty name is not legal.", "name");
690 for (int i = 0; i < modules.Length; ++i)
691 if (modules [i].name == name)
696 public override Type[] GetExportedTypes ()
698 throw not_supported ();
701 public override FileStream GetFile (string name)
703 throw not_supported ();
706 public override FileStream[] GetFiles(bool getResourceModules) {
707 throw not_supported ();
710 internal override Module[] GetModulesInternal () {
712 return new Module [0];
714 return (Module[])modules.Clone ();
717 internal override Type[] GetTypes (bool exportedOnly) {
719 if (modules != null) {
720 for (int i = 0; i < modules.Length; ++i) {
721 Type[] types = modules [i].GetTypes ();
725 Type[] tmp = new Type [res.Length + types.Length];
726 Array.Copy (res, 0, tmp, 0, res.Length);
727 Array.Copy (types, 0, tmp, res.Length, types.Length);
731 if (loaded_modules != null) {
732 for (int i = 0; i < loaded_modules.Length; ++i) {
733 Type[] types = loaded_modules [i].GetTypes ();
737 Type[] tmp = new Type [res.Length + types.Length];
738 Array.Copy (res, 0, tmp, 0, res.Length);
739 Array.Copy (types, 0, tmp, res.Length, types.Length);
745 List<Exception> exceptions = null;
746 foreach (var type in res) {
747 if (type is TypeBuilder) {
748 if (exceptions == null)
749 exceptions = new List <Exception> ();
750 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
753 if (exceptions != null)
754 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
757 return res == null ? Type.EmptyTypes : res;
760 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
761 throw not_supported ();
764 public override string[] GetManifestResourceNames() {
765 throw not_supported ();
768 public override Stream GetManifestResourceStream(string name) {
769 throw not_supported ();
771 public override Stream GetManifestResourceStream(Type type, string name) {
772 throw not_supported ();
775 internal bool IsSave {
777 return access != (uint)AssemblyBuilderAccess.Run;
781 internal bool IsRun {
783 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
785 || access == (uint)AssemblyBuilderAccess.RunAndCollect
792 internal bool IsCollectible {
794 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
798 internal string AssemblyDir {
805 * Mono extension. If this is set, the assembly can only contain one
806 * module, access should be Save, and the saved image will not contain an
809 internal bool IsModuleOnly {
811 return is_module_only;
814 is_module_only = value;
818 ModuleBuilder manifest_module;
821 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
822 // on an assemblybuilder.
824 internal override Module GetManifestModule () {
825 if (manifest_module == null)
826 manifest_module = DefineDynamicModule ("Default Dynamic Module");
827 return manifest_module;
830 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
832 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
834 this.peKind = portableExecutableKind;
835 this.machine = imageFileMachine;
837 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
838 throw new NotImplementedException (peKind.ToString ());
839 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
840 throw new NotImplementedException (machine.ToString ());
842 if (resource_writers != null) {
843 foreach (IResourceWriter writer in resource_writers) {
849 // Create a main module if not already created
850 ModuleBuilder mainModule = null;
851 if (modules != null) {
852 foreach (ModuleBuilder module in modules)
853 if (module.FullyQualifiedName == assemblyFileName)
856 if (mainModule == null)
857 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
860 mainModule.IsMain = true;
863 * Create a new entry point if the one specified
864 * by the user is in another module.
866 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
868 if (entry_point.GetParameters ().Length == 1)
869 paramTypes = new Type [] { typeof (string) };
871 paramTypes = Type.EmptyTypes;
873 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
874 ILGenerator ilgen = mb.GetILGenerator ();
875 if (paramTypes.Length == 1)
876 ilgen.Emit (OpCodes.Ldarg_0);
877 ilgen.Emit (OpCodes.Tailcall);
878 ilgen.Emit (OpCodes.Call, entry_point);
879 ilgen.Emit (OpCodes.Ret);
884 if (version_res != null)
885 DefineVersionInfoResourceImpl (assemblyFileName);
888 // runtime needs to value to embed it into the assembly
889 public_key = sn.PublicKey;
892 foreach (ModuleBuilder module in modules)
893 if (module != mainModule)
896 // Write out the main module at the end, because it needs to
897 // contain the hash of the other modules
900 if ((sn != null) && (sn.CanSign)) {
901 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
907 public void Save (string assemblyFileName)
909 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
912 public void SetEntryPoint (MethodInfo entryMethod)
914 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
917 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
919 if (entryMethod == null)
920 throw new ArgumentNullException ("entryMethod");
921 if (entryMethod.DeclaringType.Assembly != this)
922 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
924 entry_point = entryMethod;
928 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
930 if (customBuilder == null)
931 throw new ArgumentNullException ("customBuilder");
933 if (cattrs != null) {
934 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
935 cattrs.CopyTo (new_array, 0);
936 new_array [cattrs.Length] = customBuilder;
939 cattrs = new CustomAttributeBuilder [1];
940 cattrs [0] = customBuilder;
945 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
947 throw new ArgumentNullException ("con");
948 if (binaryAttribute == null)
949 throw new ArgumentNullException ("binaryAttribute");
951 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
954 private Exception not_supported () {
955 // Strange message but this is what MS.NET prints...
956 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
959 private void check_name_and_filename (string name, string fileName,
960 bool fileNeedsToExists) {
962 throw new ArgumentNullException ("name");
963 if (fileName == null)
964 throw new ArgumentNullException ("fileName");
965 if (name.Length == 0)
966 throw new ArgumentException ("Empty name is not legal.", "name");
967 if (fileName.Length == 0)
968 throw new ArgumentException ("Empty file name is not legal.", "fileName");
969 if (Path.GetFileName (fileName) != fileName)
970 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
972 // Resource files are created/searched under the assembly storage
974 string fullFileName = fileName;
976 fullFileName = Path.Combine (dir, fileName);
978 if (fileNeedsToExists && !File.Exists (fullFileName))
979 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
981 if (resources != null) {
982 for (int i = 0; i < resources.Length; ++i) {
983 if (resources [i].filename == fullFileName)
984 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
985 if (resources [i].name == name)
986 throw new ArgumentException ("Duplicate name '" + name + "'");
990 if (modules != null) {
991 for (int i = 0; i < modules.Length; ++i) {
992 // Use fileName instead of fullFileName here
993 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
994 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
995 if (modules [i].Name == name)
996 throw new ArgumentException ("Duplicate name '" + name + "'");
1001 private String create_assembly_version (String version) {
1002 String[] parts = version.Split ('.');
1003 int[] ver = new int [4] { 0, 0, 0, 0 };
1005 if ((parts.Length < 0) || (parts.Length > 4))
1006 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1008 for (int i = 0; i < parts.Length; ++i) {
1009 if (parts [i] == "*") {
1010 DateTime now = DateTime.Now;
1013 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1014 if (parts.Length == 3)
1015 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1019 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1021 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1025 ver [i] = Int32.Parse (parts [i]);
1027 catch (FormatException) {
1028 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1033 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1036 private string GetCultureString (string str)
1038 return (str == "neutral" ? String.Empty : str);
1041 internal override AssemblyName UnprotectedGetName ()
1043 AssemblyName an = base.UnprotectedGetName ();
1045 an.SetPublicKey (sn.PublicKey);
1046 an.SetPublicKeyToken (sn.PublicKeyToken);
1051 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1052 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1054 return new MonoGenericClass (gtd, typeArguments);
1057 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1059 throw new NotImplementedException ();
1062 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1064 throw new NotImplementedException ();
1067 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1069 throw new NotImplementedException ();
1072 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1074 throw new NotImplementedException ();
1077 #if NET_4_0 || MOONLIGHT || MOBILE
1078 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1081 throw new ArgumentNullException (name);
1082 if (name.Length == 0)
1083 throw new ArgumentException ("name", "Name cannot be empty");
1085 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1086 if (res is TypeBuilder) {
1088 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1094 public override Module GetModule (String name)
1097 throw new ArgumentNullException ("name");
1098 if (name.Length == 0)
1099 throw new ArgumentException ("Name can't be empty");
1101 if (modules == null)
1104 foreach (Module module in modules) {
1105 if (module.ScopeName == name)
1112 public override Module[] GetModules (bool getResourceModules)
1114 Module[] modules = GetModulesInternal ();
1116 if (!getResourceModules) {
1117 var result = new List<Module> (modules.Length);
1118 foreach (Module m in modules)
1119 if (!m.IsResource ())
1121 return result.ToArray ();
1126 public override AssemblyName GetName (bool copiedName)
1128 return base.GetName (copiedName);
1131 [MonoTODO ("This always returns an empty array")]
1132 public override AssemblyName[] GetReferencedAssemblies () {
1133 return GetReferencedAssemblies (this);
1136 public override Module[] GetLoadedModules (bool getResourceModules)
1138 return GetModules (getResourceModules);
1141 //FIXME MS has issues loading satelite assemblies from SRE
1142 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1144 return GetSatelliteAssembly (culture, null, true);
1147 //FIXME MS has issues loading satelite assemblies from SRE
1148 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1150 return GetSatelliteAssembly (culture, version, true);
1153 public override Module ManifestModule {
1155 return GetManifestModule ();
1159 public override bool GlobalAssemblyCache {
1165 public override bool IsDynamic {
1166 get { return true; }
1169 public override bool Equals (object obj)
1171 return base.Equals (obj);
1174 public override int GetHashCode ()
1176 return base.GetHashCode ();
1179 public override bool IsDefined (Type attributeType, bool inherit)
1181 return base.IsDefined (attributeType, inherit);
1184 public override object[] GetCustomAttributes (bool inherit)
1186 return base.GetCustomAttributes (inherit);
1189 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1191 return base.GetCustomAttributes (attributeType, inherit);
1194 public override string FullName {
1195 get { return base.FullName; }