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 {
74 public string filename;
75 public ResourceAttributes attrs;
80 internal struct MonoWin32Resource {
86 public MonoWin32Resource (int res_type, int res_id, int lang_id, byte[] data) {
87 this.res_type = res_type;
89 this.lang_id = lang_id;
94 internal class GenericInstanceKey {
99 internal GenericInstanceKey (Type gtd, Type[] args)
104 hash_code = gtd.GetHashCode ();
105 for (int i = 0; i < args.Length; ++i)
106 hash_code ^= args [i].GetHashCode ();
109 static bool IsBoundedVector (Type type) {
110 ArrayType at = type as ArrayType;
112 return at.GetEffectiveRank () == 1;
113 return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */
116 static bool TypeEquals (Type a, Type b) {
120 if (a.HasElementType) {
121 if (!b.HasElementType)
123 if (!TypeEquals (a.GetElementType (), b.GetElementType ()))
128 int rank = a.GetArrayRank ();
129 if (rank != b.GetArrayRank ())
131 if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b))
133 } else if (a.IsByRef) {
136 } else if (a.IsPointer) {
143 if (a.IsGenericType) {
144 if (!b.IsGenericType)
146 if (a.IsGenericParameter)
148 if (a.IsGenericParameter) //previous test should have caught it
151 if (a.IsGenericTypeDefinition) {
152 if (!b.IsGenericTypeDefinition)
155 if (b.IsGenericTypeDefinition)
157 if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ()))
160 Type[] argsA = a.GetGenericArguments ();
161 Type[] argsB = b.GetGenericArguments ();
162 for (int i = 0; i < argsA.Length; ++i) {
163 if (!TypeEquals (argsA [i], argsB [i]))
170 Now only non-generic, non compound types are left. To properly deal with user
171 types we would have to call UnderlyingSystemType, but we let them have their
172 own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't
173 depend on proper UT canonicalization.
178 public override bool Equals (object obj)
180 GenericInstanceKey other = obj as GenericInstanceKey;
183 if (gtd != other.gtd)
185 for (int i = 0; i < args.Length; ++i) {
187 Type b = other.args [i];
189 We must cannonicalize as much as we can. Using equals means that some resulting types
190 won't have the exact same types as the argument ones.
191 For example, flyweight types used array, pointer and byref will should this behavior.
192 MCS seens to be resilient to this problem so hopefully this won't show up.
194 if (a != b && !a.Equals (b))
200 public override int GetHashCode ()
208 [ComDefaultInterface (typeof (_AssemblyBuilder))]
209 [ClassInterface (ClassInterfaceType.None)]
210 [StructLayout (LayoutKind.Sequential)]
211 public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder {
212 #pragma warning disable 169, 414, 649
213 #region Sync with object-internals.h
214 private UIntPtr dynamic_assembly; /* GC-tracked */
215 private MethodInfo entry_point;
216 private ModuleBuilder[] modules;
219 private CustomAttributeBuilder[] cattrs;
220 private MonoResource[] resources;
226 PEFileKinds pekind = PEFileKinds.Dll;
229 Module[] loaded_modules;
230 MonoWin32Resource[] win32_resources;
231 private RefEmitPermissionSet[] permissions_minimum;
232 private RefEmitPermissionSet[] permissions_optional;
233 private RefEmitPermissionSet[] permissions_refused;
234 PortableExecutableKinds peKind;
235 ImageFileMachine machine;
236 bool corlib_internal;
237 Type[] type_forwarders;
240 #pragma warning restore 169, 414, 649
242 internal Type corlib_object_type = typeof (System.Object);
243 internal Type corlib_value_type = typeof (System.ValueType);
244 internal Type corlib_enum_type = typeof (System.Enum);
245 internal Type corlib_void_type = typeof (void);
246 ArrayList resource_writers = null;
247 Win32VersionResource version_res;
250 private Mono.Security.StrongName sn;
251 NativeResourceType native_resource;
252 string versioninfo_culture;
254 [MethodImplAttribute(MethodImplOptions.InternalCall)]
255 private static extern void basic_init (AssemblyBuilder ab);
257 /* Keep this in sync with codegen.cs in mcs */
258 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
260 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
262 /* This is obsolete now, as mcs doesn't use SRE any more */
263 if ((access & COMPILER_ACCESS) != 0)
264 throw new NotImplementedException ("COMPILER_ACCESS is no longer supperted, use a newer mcs.");
267 // only "Run" is supported by Silverlight
268 // however SMCS requires more than this but runs outside the CoreCLR sandbox
269 if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run))
270 throw new ArgumentException ("access");
273 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
274 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
275 "Argument value {0} is not valid.", (int) access),
279 this.access = (uint)access;
280 flags = (uint) n.Flags;
282 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
283 if (IsSave && (directory == null || directory.Length == 0)) {
284 dir = Directory.GetCurrentDirectory ();
289 /* Set defaults from n */
290 if (n.CultureInfo != null) {
291 culture = n.CultureInfo.Name;
292 versioninfo_culture = n.CultureInfo.Name;
294 Version v = n.Version;
296 version = v.ToString ();
299 if (n.KeyPair != null) {
300 // full keypair is available (for signing)
301 sn = n.KeyPair.StrongName ();
303 // public key is available (for delay-signing)
304 byte[] pk = n.GetPublicKey ();
305 if ((pk != null) && (pk.Length > 0)) {
306 sn = new Mono.Security.StrongName (pk);
311 flags |= (uint) AssemblyNameFlags.PublicKey;
313 this.corlib_internal = corlib_internal;
315 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
317 foreach (byte pkb in sn.PublicKeyToken) {
318 string part = pkb.ToString("x2");
319 this.pktoken[pkti++] = (byte)part[0];
320 this.pktoken[pkti++] = (byte)part[1];
327 public override string CodeBase {
329 throw not_supported ();
333 public override MethodInfo EntryPoint {
339 public override string Location {
341 throw not_supported ();
345 /* This is to keep signature compatibility with MS.NET */
346 public override string ImageRuntimeVersion {
348 return base.ImageRuntimeVersion;
353 public override bool ReflectionOnly {
354 get { return base.ReflectionOnly; }
357 public void AddResourceFile (string name, string fileName)
359 AddResourceFile (name, fileName, ResourceAttributes.Public);
362 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
364 AddResourceFile (name, fileName, attribute, true);
367 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
369 check_name_and_filename (name, fileName, fileNeedsToExists);
371 // Resource files are created/searched under the assembly storage
374 fileName = Path.Combine (dir, fileName);
376 if (resources != null) {
377 MonoResource[] new_r = new MonoResource [resources.Length + 1];
378 System.Array.Copy(resources, new_r, resources.Length);
381 resources = new MonoResource [1];
383 int p = resources.Length - 1;
384 resources [p].name = name;
385 resources [p].filename = fileName;
386 resources [p].attrs = attribute;
389 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
393 throw new InvalidOperationException ("Assembly was already saved.");
395 // required for base Assembly class (so the permissions
396 // can be used even if the assembly isn't saved to disk)
398 _optional = optional;
401 // required to reuse AddDeclarativeSecurity support
402 // already present in the runtime
403 if (required != null) {
404 permissions_minimum = new RefEmitPermissionSet [1];
405 permissions_minimum [0] = new RefEmitPermissionSet (
406 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
408 if (optional != null) {
409 permissions_optional = new RefEmitPermissionSet [1];
410 permissions_optional [0] = new RefEmitPermissionSet (
411 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
413 if (refused != null) {
414 permissions_refused = new RefEmitPermissionSet [1];
415 permissions_refused [0] = new RefEmitPermissionSet (
416 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
421 // Still in use by al.exe
422 internal void EmbedResourceFile (string name, string fileName)
424 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
427 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
429 if (resources != null) {
430 MonoResource[] new_r = new MonoResource [resources.Length + 1];
431 System.Array.Copy(resources, new_r, resources.Length);
434 resources = new MonoResource [1];
436 int p = resources.Length - 1;
437 resources [p].name = name;
438 resources [p].attrs = attribute;
440 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
442 resources [p].data = new byte [len];
443 s.Read (resources [p].data, 0, (int)len);
449 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
451 if (resources != null) {
452 MonoResource[] new_r = new MonoResource [resources.Length + 1];
453 System.Array.Copy(resources, new_r, resources.Length);
456 resources = new MonoResource [1];
458 int p = resources.Length - 1;
459 resources [p].name = name;
460 resources [p].attrs = attribute;
461 resources [p].data = blob;
465 public ModuleBuilder DefineDynamicModule (string name)
467 return DefineDynamicModule (name, name, false, true);
470 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
472 return DefineDynamicModule (name, name, emitSymbolInfo, true);
475 public ModuleBuilder DefineDynamicModule(string name, string fileName)
477 return DefineDynamicModule (name, fileName, false, false);
480 public ModuleBuilder DefineDynamicModule (string name, string fileName,
483 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
486 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
488 check_name_and_filename (name, fileName, false);
491 if (Path.GetExtension (fileName) == String.Empty)
492 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
494 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
496 throw new InvalidOperationException ("Assembly was already saved.");
499 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
501 if ((modules != null) && is_module_only)
502 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
504 if (modules != null) {
505 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
506 System.Array.Copy(modules, new_modules, modules.Length);
507 modules = new_modules;
509 modules = new ModuleBuilder [1];
511 modules [modules.Length - 1] = r;
515 public IResourceWriter DefineResource (string name, string description, string fileName)
517 return DefineResource (name, description, fileName, ResourceAttributes.Public);
520 public IResourceWriter DefineResource (string name, string description,
521 string fileName, ResourceAttributes attribute)
523 IResourceWriter writer;
525 // description seems to be ignored
526 AddResourceFile (name, fileName, attribute, false);
527 writer = new ResourceWriter (fileName);
528 if (resource_writers == null)
529 resource_writers = new ArrayList ();
530 resource_writers.Add (writer);
534 private void AddUnmanagedResource (Win32Resource res) {
535 MemoryStream ms = new MemoryStream ();
538 if (win32_resources != null) {
539 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
540 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
541 win32_resources = new_res;
544 win32_resources = new MonoWin32Resource [1];
546 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
549 [MonoTODO ("Not currently implemenented")]
550 public void DefineUnmanagedResource (byte[] resource)
552 if (resource == null)
553 throw new ArgumentNullException ("resource");
554 if (native_resource != NativeResourceType.None)
555 throw new ArgumentException ("Native resource has already been defined.");
557 // avoid definition of more than one unmanaged resource
558 native_resource = NativeResourceType.Unmanaged;
561 * The format of the argument byte array is not documented
562 * so this method is impossible to implement.
564 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
567 throw new NotImplementedException ();
570 public void DefineUnmanagedResource (string resourceFileName)
572 if (resourceFileName == null)
573 throw new ArgumentNullException ("resourceFileName");
574 if (resourceFileName.Length == 0)
575 throw new ArgumentException ("resourceFileName");
576 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
577 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
578 if (native_resource != NativeResourceType.None)
579 throw new ArgumentException ("Native resource has already been defined.");
581 // avoid definition of more than one unmanaged resource
582 native_resource = NativeResourceType.Unmanaged;
584 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
585 Win32ResFileReader reader = new Win32ResFileReader (fs);
587 foreach (Win32EncodedResource res in reader.ReadResources ()) {
588 if (res.Name.IsName || res.Type.IsName)
589 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
591 AddUnmanagedResource (res);
596 public void DefineVersionInfoResource ()
598 if (native_resource != NativeResourceType.None)
599 throw new ArgumentException ("Native resource has already been defined.");
601 // avoid definition of more than one unmanaged resource
602 native_resource = NativeResourceType.Assembly;
604 version_res = new Win32VersionResource (1, 0, false);
607 public void DefineVersionInfoResource (string product, string productVersion,
608 string company, string copyright, string trademark)
610 if (native_resource != NativeResourceType.None)
611 throw new ArgumentException ("Native resource has already been defined.");
613 // avoid definition of more than one unmanaged resource
614 native_resource = NativeResourceType.Explicit;
617 * We can only create the resource later, when the file name and
618 * the binary version is known.
621 version_res = new Win32VersionResource (1, 0, false);
622 version_res.ProductName = product != null ? product : " ";
623 version_res.ProductVersion = productVersion != null ? productVersion : " ";
624 version_res.CompanyName = company != null ? company : " ";
625 version_res.LegalCopyright = copyright != null ? copyright : " ";
626 version_res.LegalTrademarks = trademark != null ? trademark : " ";
629 private void DefineVersionInfoResourceImpl (string fileName)
631 if (versioninfo_culture != null)
632 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
633 version_res.Version = version == null ? "0.0.0.0" : version;
635 if (cattrs != null) {
636 switch (native_resource) {
637 case NativeResourceType.Assembly:
638 foreach (CustomAttributeBuilder cb in cattrs) {
639 string attrname = cb.Ctor.ReflectedType.FullName;
641 if (attrname == "System.Reflection.AssemblyProductAttribute")
642 version_res.ProductName = cb.string_arg ();
643 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
644 version_res.CompanyName = cb.string_arg ();
645 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
646 version_res.LegalCopyright = cb.string_arg ();
647 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
648 version_res.LegalTrademarks = cb.string_arg ();
649 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
650 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
651 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
652 version_res.FileVersion = cb.string_arg ();
653 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
654 version_res.ProductVersion = cb.string_arg ();
655 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
656 version_res.FileDescription = cb.string_arg ();
657 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
658 version_res.Comments = cb.string_arg ();
661 case NativeResourceType.Explicit:
662 foreach (CustomAttributeBuilder cb in cattrs) {
663 string attrname = cb.Ctor.ReflectedType.FullName;
665 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
666 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
667 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
668 version_res.Comments = cb.string_arg ();
674 version_res.OriginalFilename = fileName;
675 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
677 AddUnmanagedResource (version_res);
680 public ModuleBuilder GetDynamicModule (string name)
683 throw new ArgumentNullException ("name");
684 if (name.Length == 0)
685 throw new ArgumentException ("Empty name is not legal.", "name");
688 for (int i = 0; i < modules.Length; ++i)
689 if (modules [i].name == name)
694 public override Type[] GetExportedTypes ()
696 throw not_supported ();
699 public override FileStream GetFile (string name)
701 throw not_supported ();
704 public override FileStream[] GetFiles(bool getResourceModules) {
705 throw not_supported ();
708 internal override Module[] GetModulesInternal () {
710 return new Module [0];
712 return (Module[])modules.Clone ();
715 internal override Type[] GetTypes (bool exportedOnly) {
717 if (modules != null) {
718 for (int i = 0; i < modules.Length; ++i) {
719 Type[] types = modules [i].GetTypes ();
723 Type[] tmp = new Type [res.Length + types.Length];
724 Array.Copy (res, 0, tmp, 0, res.Length);
725 Array.Copy (types, 0, tmp, res.Length, types.Length);
729 if (loaded_modules != null) {
730 for (int i = 0; i < loaded_modules.Length; ++i) {
731 Type[] types = loaded_modules [i].GetTypes ();
735 Type[] tmp = new Type [res.Length + types.Length];
736 Array.Copy (res, 0, tmp, 0, res.Length);
737 Array.Copy (types, 0, tmp, res.Length, types.Length);
743 List<Exception> exceptions = null;
744 foreach (var type in res) {
745 if (type is TypeBuilder) {
746 if (exceptions == null)
747 exceptions = new List <Exception> ();
748 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
751 if (exceptions != null)
752 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
755 return res == null ? Type.EmptyTypes : res;
758 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
759 throw not_supported ();
762 public override string[] GetManifestResourceNames() {
763 throw not_supported ();
766 public override Stream GetManifestResourceStream(string name) {
767 throw not_supported ();
769 public override Stream GetManifestResourceStream(Type type, string name) {
770 throw not_supported ();
773 internal bool IsSave {
775 return access != (uint)AssemblyBuilderAccess.Run;
779 internal bool IsRun {
781 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
783 || access == (uint)AssemblyBuilderAccess.RunAndCollect
790 internal bool IsCollectible {
792 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
796 internal string AssemblyDir {
803 * Mono extension. If this is set, the assembly can only contain one
804 * module, access should be Save, and the saved image will not contain an
807 internal bool IsModuleOnly {
809 return is_module_only;
812 is_module_only = value;
816 ModuleBuilder manifest_module;
819 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
820 // on an assemblybuilder.
822 internal override Module GetManifestModule () {
823 if (manifest_module == null)
824 manifest_module = DefineDynamicModule ("Default Dynamic Module");
825 return manifest_module;
828 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
830 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
832 this.peKind = portableExecutableKind;
833 this.machine = imageFileMachine;
835 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
836 throw new NotImplementedException (peKind.ToString ());
837 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
838 throw new NotImplementedException (machine.ToString ());
840 if (resource_writers != null) {
841 foreach (IResourceWriter writer in resource_writers) {
847 // Create a main module if not already created
848 ModuleBuilder mainModule = null;
849 if (modules != null) {
850 foreach (ModuleBuilder module in modules)
851 if (module.FullyQualifiedName == assemblyFileName)
854 if (mainModule == null)
855 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
858 mainModule.IsMain = true;
861 * Create a new entry point if the one specified
862 * by the user is in another module.
864 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
866 if (entry_point.GetParameters ().Length == 1)
867 paramTypes = new Type [] { typeof (string) };
869 paramTypes = Type.EmptyTypes;
871 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
872 ILGenerator ilgen = mb.GetILGenerator ();
873 if (paramTypes.Length == 1)
874 ilgen.Emit (OpCodes.Ldarg_0);
875 ilgen.Emit (OpCodes.Tailcall);
876 ilgen.Emit (OpCodes.Call, entry_point);
877 ilgen.Emit (OpCodes.Ret);
882 if (version_res != null)
883 DefineVersionInfoResourceImpl (assemblyFileName);
886 // runtime needs to value to embed it into the assembly
887 public_key = sn.PublicKey;
890 foreach (ModuleBuilder module in modules)
891 if (module != mainModule)
894 // Write out the main module at the end, because it needs to
895 // contain the hash of the other modules
898 if ((sn != null) && (sn.CanSign)) {
899 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
905 public void Save (string assemblyFileName)
907 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
910 public void SetEntryPoint (MethodInfo entryMethod)
912 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
915 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
917 if (entryMethod == null)
918 throw new ArgumentNullException ("entryMethod");
919 if (entryMethod.DeclaringType.Assembly != this)
920 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
922 entry_point = entryMethod;
926 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
928 if (customBuilder == null)
929 throw new ArgumentNullException ("customBuilder");
931 if (cattrs != null) {
932 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
933 cattrs.CopyTo (new_array, 0);
934 new_array [cattrs.Length] = customBuilder;
937 cattrs = new CustomAttributeBuilder [1];
938 cattrs [0] = customBuilder;
943 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
945 throw new ArgumentNullException ("con");
946 if (binaryAttribute == null)
947 throw new ArgumentNullException ("binaryAttribute");
949 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
952 private Exception not_supported () {
953 // Strange message but this is what MS.NET prints...
954 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
957 private void check_name_and_filename (string name, string fileName,
958 bool fileNeedsToExists) {
960 throw new ArgumentNullException ("name");
961 if (fileName == null)
962 throw new ArgumentNullException ("fileName");
963 if (name.Length == 0)
964 throw new ArgumentException ("Empty name is not legal.", "name");
965 if (fileName.Length == 0)
966 throw new ArgumentException ("Empty file name is not legal.", "fileName");
967 if (Path.GetFileName (fileName) != fileName)
968 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
970 // Resource files are created/searched under the assembly storage
972 string fullFileName = fileName;
974 fullFileName = Path.Combine (dir, fileName);
976 if (fileNeedsToExists && !File.Exists (fullFileName))
977 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
979 if (resources != null) {
980 for (int i = 0; i < resources.Length; ++i) {
981 if (resources [i].filename == fullFileName)
982 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
983 if (resources [i].name == name)
984 throw new ArgumentException ("Duplicate name '" + name + "'");
988 if (modules != null) {
989 for (int i = 0; i < modules.Length; ++i) {
990 // Use fileName instead of fullFileName here
991 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
992 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
993 if (modules [i].Name == name)
994 throw new ArgumentException ("Duplicate name '" + name + "'");
999 private String create_assembly_version (String version) {
1000 String[] parts = version.Split ('.');
1001 int[] ver = new int [4] { 0, 0, 0, 0 };
1003 if ((parts.Length < 0) || (parts.Length > 4))
1004 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1006 for (int i = 0; i < parts.Length; ++i) {
1007 if (parts [i] == "*") {
1008 DateTime now = DateTime.Now;
1011 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1012 if (parts.Length == 3)
1013 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1017 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1019 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1023 ver [i] = Int32.Parse (parts [i]);
1025 catch (FormatException) {
1026 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1031 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1034 private string GetCultureString (string str)
1036 return (str == "neutral" ? String.Empty : str);
1039 internal override AssemblyName UnprotectedGetName ()
1041 AssemblyName an = base.UnprotectedGetName ();
1043 an.SetPublicKey (sn.PublicKey);
1044 an.SetPublicKeyToken (sn.PublicKeyToken);
1049 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1050 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1052 return new MonoGenericClass (gtd, typeArguments);
1055 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1057 throw new NotImplementedException ();
1060 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1062 throw new NotImplementedException ();
1065 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1067 throw new NotImplementedException ();
1070 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1072 throw new NotImplementedException ();
1075 #if NET_4_0 || MOONLIGHT || MOBILE
1076 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1079 throw new ArgumentNullException (name);
1080 if (name.Length == 0)
1081 throw new ArgumentException ("name", "Name cannot be empty");
1083 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1084 if (res is TypeBuilder) {
1086 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1092 public override Module GetModule (String name)
1095 throw new ArgumentNullException ("name");
1096 if (name.Length == 0)
1097 throw new ArgumentException ("Name can't be empty");
1099 if (modules == null)
1102 foreach (Module module in modules) {
1103 if (module.ScopeName == name)
1110 public override Module[] GetModules (bool getResourceModules)
1112 Module[] modules = GetModulesInternal ();
1114 if (!getResourceModules) {
1115 var result = new List<Module> (modules.Length);
1116 foreach (Module m in modules)
1117 if (!m.IsResource ())
1119 return result.ToArray ();
1124 public override AssemblyName GetName (bool copiedName)
1126 return base.GetName (copiedName);
1129 [MonoTODO ("This always returns an empty array")]
1130 public override AssemblyName[] GetReferencedAssemblies () {
1131 return GetReferencedAssemblies (this);
1134 public override Module[] GetLoadedModules (bool getResourceModules)
1136 return GetModules (getResourceModules);
1139 //FIXME MS has issues loading satelite assemblies from SRE
1140 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1142 return GetSatelliteAssembly (culture, null, true);
1145 //FIXME MS has issues loading satelite assemblies from SRE
1146 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1148 return GetSatelliteAssembly (culture, version, true);
1151 public override Module ManifestModule {
1153 return GetManifestModule ();
1157 public override bool GlobalAssemblyCache {
1163 public override bool IsDynamic {
1164 get { return true; }
1167 public override bool Equals (object obj)
1169 return base.Equals (obj);
1172 public override int GetHashCode ()
1174 return base.GetHashCode ();
1177 public override bool IsDefined (Type attributeType, bool inherit)
1179 return base.IsDefined (attributeType, inherit);
1182 public override object[] GetCustomAttributes (bool inherit)
1184 return base.GetCustomAttributes (inherit);
1187 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1189 return base.GetCustomAttributes (attributeType, inherit);
1192 public override string FullName {
1193 get { return base.FullName; }