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 [MethodImplAttribute(MethodImplOptions.InternalCall)]
261 static extern void UpdateNativeCustomAttributes (AssemblyBuilder ab);
263 /* Keep this in sync with codegen.cs in mcs */
264 private const AssemblyBuilderAccess COMPILER_ACCESS = (AssemblyBuilderAccess) 0x800;
266 internal AssemblyBuilder (AssemblyName n, string directory, AssemblyBuilderAccess access, bool corlib_internal)
268 /* This is obsolete now, as mcs doesn't use SRE any more */
269 if ((access & COMPILER_ACCESS) != 0)
270 throw new NotImplementedException ("COMPILER_ACCESS is no longer supperted, use a newer mcs.");
272 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access))
273 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
274 "Argument value {0} is not valid.", (int) access),
278 this.access = (uint)access;
279 flags = (uint) n.Flags;
281 // don't call GetCurrentDirectory for Run-only builders (CAS may not like that)
282 if (IsSave && (directory == null || directory.Length == 0)) {
283 dir = Directory.GetCurrentDirectory ();
288 /* Set defaults from n */
289 if (n.CultureInfo != null) {
290 culture = n.CultureInfo.Name;
291 versioninfo_culture = n.CultureInfo.Name;
293 Version v = n.Version;
295 version = v.ToString ();
298 if (n.KeyPair != null) {
299 // full keypair is available (for signing)
300 sn = n.KeyPair.StrongName ();
302 // public key is available (for delay-signing)
303 byte[] pk = n.GetPublicKey ();
304 if ((pk != null) && (pk.Length > 0)) {
305 sn = new Mono.Security.StrongName (pk);
310 flags |= (uint) AssemblyNameFlags.PublicKey;
312 this.corlib_internal = corlib_internal;
314 this.pktoken = new byte[sn.PublicKeyToken.Length * 2];
316 foreach (byte pkb in sn.PublicKeyToken) {
317 string part = pkb.ToString("x2");
318 this.pktoken[pkti++] = (byte)part[0];
319 this.pktoken[pkti++] = (byte)part[1];
326 public override string CodeBase {
328 throw not_supported ();
332 public override MethodInfo EntryPoint {
338 public override string Location {
340 throw not_supported ();
344 /* This is to keep signature compatibility with MS.NET */
345 public override string ImageRuntimeVersion {
347 return base.ImageRuntimeVersion;
352 public override bool ReflectionOnly {
353 get { return base.ReflectionOnly; }
356 public void AddResourceFile (string name, string fileName)
358 AddResourceFile (name, fileName, ResourceAttributes.Public);
361 public void AddResourceFile (string name, string fileName, ResourceAttributes attribute)
363 AddResourceFile (name, fileName, attribute, true);
366 private void AddResourceFile (string name, string fileName, ResourceAttributes attribute, bool fileNeedsToExists)
368 check_name_and_filename (name, fileName, fileNeedsToExists);
370 // Resource files are created/searched under the assembly storage
373 fileName = Path.Combine (dir, fileName);
375 if (resources != null) {
376 MonoResource[] new_r = new MonoResource [resources.Length + 1];
377 System.Array.Copy(resources, new_r, resources.Length);
380 resources = new MonoResource [1];
382 int p = resources.Length - 1;
383 resources [p].name = name;
384 resources [p].filename = fileName;
385 resources [p].attrs = attribute;
388 internal void AddPermissionRequests (PermissionSet required, PermissionSet optional, PermissionSet refused)
392 throw new InvalidOperationException ("Assembly was already saved.");
394 // required for base Assembly class (so the permissions
395 // can be used even if the assembly isn't saved to disk)
397 _optional = optional;
400 // required to reuse AddDeclarativeSecurity support
401 // already present in the runtime
402 if (required != null) {
403 permissions_minimum = new RefEmitPermissionSet [1];
404 permissions_minimum [0] = new RefEmitPermissionSet (
405 SecurityAction.RequestMinimum, required.ToXml ().ToString ());
407 if (optional != null) {
408 permissions_optional = new RefEmitPermissionSet [1];
409 permissions_optional [0] = new RefEmitPermissionSet (
410 SecurityAction.RequestOptional, optional.ToXml ().ToString ());
412 if (refused != null) {
413 permissions_refused = new RefEmitPermissionSet [1];
414 permissions_refused [0] = new RefEmitPermissionSet (
415 SecurityAction.RequestRefuse, refused.ToXml ().ToString ());
420 // Still in use by al.exe
421 internal void EmbedResourceFile (string name, string fileName)
423 EmbedResourceFile (name, fileName, ResourceAttributes.Public);
426 void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute)
428 if (resources != null) {
429 MonoResource[] new_r = new MonoResource [resources.Length + 1];
430 System.Array.Copy(resources, new_r, resources.Length);
433 resources = new MonoResource [1];
435 int p = resources.Length - 1;
436 resources [p].name = name;
437 resources [p].attrs = attribute;
439 FileStream s = new FileStream (fileName, FileMode.Open, FileAccess.Read);
441 resources [p].data = new byte [len];
442 s.Read (resources [p].data, 0, (int)len);
448 internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute)
450 if (resources != null) {
451 MonoResource[] new_r = new MonoResource [resources.Length + 1];
452 System.Array.Copy(resources, new_r, resources.Length);
455 resources = new MonoResource [1];
457 int p = resources.Length - 1;
458 resources [p].name = name;
459 resources [p].attrs = attribute;
460 resources [p].data = blob;
464 public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access)
467 throw new ArgumentNullException ("name");
469 return new AssemblyBuilder (name, null, access, false);
472 public static AssemblyBuilder DefineDynamicAssembly (AssemblyName name, AssemblyBuilderAccess access, IEnumerable<CustomAttributeBuilder> assemblyAttributes)
474 var ab = DefineDynamicAssembly (name, access);
475 foreach (var attr in assemblyAttributes) {
476 ab.SetCustomAttribute (attr);
482 public ModuleBuilder DefineDynamicModule (string name)
484 return DefineDynamicModule (name, name, false, true);
487 public ModuleBuilder DefineDynamicModule (string name, bool emitSymbolInfo)
489 return DefineDynamicModule (name, name, emitSymbolInfo, true);
492 public ModuleBuilder DefineDynamicModule(string name, string fileName)
494 return DefineDynamicModule (name, fileName, false, false);
497 public ModuleBuilder DefineDynamicModule (string name, string fileName,
500 return DefineDynamicModule (name, fileName, emitSymbolInfo, false);
503 private ModuleBuilder DefineDynamicModule (string name, string fileName, bool emitSymbolInfo, bool transient)
505 check_name_and_filename (name, fileName, false);
508 if (Path.GetExtension (fileName) == String.Empty)
509 throw new ArgumentException ("Module file name '" + fileName + "' must have file extension.");
511 throw new NotSupportedException ("Persistable modules are not supported in a dynamic assembly created with AssemblyBuilderAccess.Run");
513 throw new InvalidOperationException ("Assembly was already saved.");
516 ModuleBuilder r = new ModuleBuilder (this, name, fileName, emitSymbolInfo, transient);
518 if ((modules != null) && is_module_only)
519 throw new InvalidOperationException ("A module-only assembly can only contain one module.");
521 if (modules != null) {
522 ModuleBuilder[] new_modules = new ModuleBuilder [modules.Length + 1];
523 System.Array.Copy(modules, new_modules, modules.Length);
524 modules = new_modules;
526 modules = new ModuleBuilder [1];
528 modules [modules.Length - 1] = r;
532 public IResourceWriter DefineResource (string name, string description, string fileName)
534 return DefineResource (name, description, fileName, ResourceAttributes.Public);
537 public IResourceWriter DefineResource (string name, string description,
538 string fileName, ResourceAttributes attribute)
540 IResourceWriter writer;
542 // description seems to be ignored
543 AddResourceFile (name, fileName, attribute, false);
544 writer = new ResourceWriter (fileName);
545 if (resource_writers == null)
546 resource_writers = new ArrayList ();
547 resource_writers.Add (writer);
551 private void AddUnmanagedResource (Win32Resource res) {
552 MemoryStream ms = new MemoryStream ();
555 if (win32_resources != null) {
556 MonoWin32Resource[] new_res = new MonoWin32Resource [win32_resources.Length + 1];
557 System.Array.Copy (win32_resources, new_res, win32_resources.Length);
558 win32_resources = new_res;
561 win32_resources = new MonoWin32Resource [1];
563 win32_resources [win32_resources.Length - 1] = new MonoWin32Resource (res.Type.Id, res.Name.Id, res.Language, ms.ToArray ());
566 [MonoTODO ("Not currently implemenented")]
567 public void DefineUnmanagedResource (byte[] resource)
569 if (resource == null)
570 throw new ArgumentNullException ("resource");
571 if (native_resource != NativeResourceType.None)
572 throw new ArgumentException ("Native resource has already been defined.");
574 // avoid definition of more than one unmanaged resource
575 native_resource = NativeResourceType.Unmanaged;
578 * The format of the argument byte array is not documented
579 * so this method is impossible to implement.
581 * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless
584 throw new NotImplementedException ();
587 public void DefineUnmanagedResource (string resourceFileName)
589 if (resourceFileName == null)
590 throw new ArgumentNullException ("resourceFileName");
591 if (resourceFileName.Length == 0)
592 throw new ArgumentException ("resourceFileName");
593 if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
594 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exist or is a directory.");
595 if (native_resource != NativeResourceType.None)
596 throw new ArgumentException ("Native resource has already been defined.");
598 // avoid definition of more than one unmanaged resource
599 native_resource = NativeResourceType.Unmanaged;
601 using (FileStream fs = new FileStream (resourceFileName, FileMode.Open, FileAccess.Read)) {
602 Win32ResFileReader reader = new Win32ResFileReader (fs);
604 foreach (Win32EncodedResource res in reader.ReadResources ()) {
605 if (res.Name.IsName || res.Type.IsName)
606 throw new InvalidOperationException ("resource files with named resources or non-default resource types are not supported.");
608 AddUnmanagedResource (res);
613 public void DefineVersionInfoResource ()
615 if (native_resource != NativeResourceType.None)
616 throw new ArgumentException ("Native resource has already been defined.");
618 // avoid definition of more than one unmanaged resource
619 native_resource = NativeResourceType.Assembly;
621 version_res = new Win32VersionResource (1, 0, false);
624 public void DefineVersionInfoResource (string product, string productVersion,
625 string company, string copyright, string trademark)
627 if (native_resource != NativeResourceType.None)
628 throw new ArgumentException ("Native resource has already been defined.");
630 // avoid definition of more than one unmanaged resource
631 native_resource = NativeResourceType.Explicit;
634 * We can only create the resource later, when the file name and
635 * the binary version is known.
638 version_res = new Win32VersionResource (1, 0, false);
639 version_res.ProductName = product != null ? product : " ";
640 version_res.ProductVersion = productVersion != null ? productVersion : " ";
641 version_res.CompanyName = company != null ? company : " ";
642 version_res.LegalCopyright = copyright != null ? copyright : " ";
643 version_res.LegalTrademarks = trademark != null ? trademark : " ";
646 private void DefineVersionInfoResourceImpl (string fileName)
648 if (versioninfo_culture != null)
649 version_res.FileLanguage = new CultureInfo (versioninfo_culture).LCID;
650 version_res.Version = version == null ? "0.0.0.0" : version;
652 if (cattrs != null) {
653 switch (native_resource) {
654 case NativeResourceType.Assembly:
655 foreach (CustomAttributeBuilder cb in cattrs) {
656 string attrname = cb.Ctor.ReflectedType.FullName;
658 if (attrname == "System.Reflection.AssemblyProductAttribute")
659 version_res.ProductName = cb.string_arg ();
660 else if (attrname == "System.Reflection.AssemblyCompanyAttribute")
661 version_res.CompanyName = cb.string_arg ();
662 else if (attrname == "System.Reflection.AssemblyCopyrightAttribute")
663 version_res.LegalCopyright = cb.string_arg ();
664 else if (attrname == "System.Reflection.AssemblyTrademarkAttribute")
665 version_res.LegalTrademarks = cb.string_arg ();
666 else if (attrname == "System.Reflection.AssemblyCultureAttribute") {
667 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
668 } else if (attrname == "System.Reflection.AssemblyFileVersionAttribute") {
669 version_res.FileVersion = cb.string_arg ();
670 } else if (attrname == "System.Reflection.AssemblyInformationalVersionAttribute")
671 version_res.ProductVersion = cb.string_arg ();
672 else if (attrname == "System.Reflection.AssemblyTitleAttribute")
673 version_res.FileDescription = cb.string_arg ();
674 else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
675 version_res.Comments = cb.string_arg ();
678 case NativeResourceType.Explicit:
679 foreach (CustomAttributeBuilder cb in cattrs) {
680 string attrname = cb.Ctor.ReflectedType.FullName;
682 if (attrname == "System.Reflection.AssemblyCultureAttribute") {
683 version_res.FileLanguage = new CultureInfo (cb.string_arg ()).LCID;
684 } else if (attrname == "System.Reflection.AssemblyDescriptionAttribute")
685 version_res.Comments = cb.string_arg ();
691 version_res.OriginalFilename = fileName;
692 version_res.InternalName = Path.GetFileNameWithoutExtension (fileName);
694 AddUnmanagedResource (version_res);
697 public ModuleBuilder GetDynamicModule (string name)
700 throw new ArgumentNullException ("name");
701 if (name.Length == 0)
702 throw new ArgumentException ("Empty name is not legal.", "name");
705 for (int i = 0; i < modules.Length; ++i)
706 if (modules [i].name == name)
711 public override Type[] GetExportedTypes ()
713 throw not_supported ();
716 public override FileStream GetFile (string name)
718 throw not_supported ();
721 public override FileStream[] GetFiles(bool getResourceModules) {
722 throw not_supported ();
725 internal override Module[] GetModulesInternal () {
727 return new Module [0];
729 return (Module[])modules.Clone ();
732 internal override Type[] GetTypes (bool exportedOnly) {
734 if (modules != null) {
735 for (int i = 0; i < modules.Length; ++i) {
736 Type[] types = modules [i].GetTypes ();
740 Type[] tmp = new Type [res.Length + types.Length];
741 Array.Copy (res, 0, tmp, 0, res.Length);
742 Array.Copy (types, 0, tmp, res.Length, types.Length);
746 if (loaded_modules != null) {
747 for (int i = 0; i < loaded_modules.Length; ++i) {
748 Type[] types = loaded_modules [i].GetTypes ();
752 Type[] tmp = new Type [res.Length + types.Length];
753 Array.Copy (res, 0, tmp, 0, res.Length);
754 Array.Copy (types, 0, tmp, res.Length, types.Length);
760 List<Exception> exceptions = null;
761 foreach (var type in res) {
762 if (type is TypeBuilder) {
763 if (exceptions == null)
764 exceptions = new List <Exception> ();
765 exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName)));
768 if (exceptions != null)
769 throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ());
772 return res == null ? Type.EmptyTypes : res;
775 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName) {
776 throw not_supported ();
779 public override string[] GetManifestResourceNames() {
780 throw not_supported ();
783 public override Stream GetManifestResourceStream(string name) {
784 throw not_supported ();
786 public override Stream GetManifestResourceStream(Type type, string name) {
787 throw not_supported ();
790 internal bool IsSave {
792 return access != (uint)AssemblyBuilderAccess.Run;
796 internal bool IsRun {
798 return access == (uint)AssemblyBuilderAccess.Run || access == (uint)AssemblyBuilderAccess.RunAndSave
799 || access == (uint)AssemblyBuilderAccess.RunAndCollect
805 internal bool IsCollectible {
807 return access == (uint)AssemblyBuilderAccess.RunAndCollect;
811 internal string AssemblyDir {
818 * Mono extension. If this is set, the assembly can only contain one
819 * module, access should be Save, and the saved image will not contain an
822 internal bool IsModuleOnly {
824 return is_module_only;
827 is_module_only = value;
831 ModuleBuilder manifest_module;
834 // MS.NET seems to return a ModuleBuilder when GetManifestModule () is called
835 // on an assemblybuilder.
837 internal override Module GetManifestModule () {
838 if (manifest_module == null)
839 manifest_module = DefineDynamicModule ("Default Dynamic Module");
840 return manifest_module;
843 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")]
845 void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
847 this.peKind = portableExecutableKind;
848 this.machine = imageFileMachine;
850 if ((peKind & PortableExecutableKinds.PE32Plus) != 0 || (peKind & PortableExecutableKinds.Unmanaged32Bit) != 0)
851 throw new NotImplementedException (peKind.ToString ());
852 if (machine == ImageFileMachine.IA64 || machine == ImageFileMachine.AMD64)
853 throw new NotImplementedException (machine.ToString ());
855 if (resource_writers != null) {
856 foreach (IResourceWriter writer in resource_writers) {
862 // Create a main module if not already created
863 ModuleBuilder mainModule = null;
864 if (modules != null) {
865 foreach (ModuleBuilder module in modules)
866 if (module.FullyQualifiedName == assemblyFileName)
869 if (mainModule == null)
870 mainModule = DefineDynamicModule ("RefEmit_OnDiskManifestModule", assemblyFileName);
873 mainModule.IsMain = true;
876 * Create a new entry point if the one specified
877 * by the user is in another module.
879 if ((entry_point != null) && entry_point.DeclaringType.Module != mainModule) {
881 if (entry_point.GetParametersCount () == 1)
882 paramTypes = new Type [] { typeof (string) };
884 paramTypes = Type.EmptyTypes;
886 MethodBuilder mb = mainModule.DefineGlobalMethod ("__EntryPoint$", MethodAttributes.Static|MethodAttributes.PrivateScope, entry_point.ReturnType, paramTypes);
887 ILGenerator ilgen = mb.GetILGenerator ();
888 if (paramTypes.Length == 1)
889 ilgen.Emit (OpCodes.Ldarg_0);
890 ilgen.Emit (OpCodes.Tailcall);
891 ilgen.Emit (OpCodes.Call, entry_point);
892 ilgen.Emit (OpCodes.Ret);
897 if (version_res != null)
898 DefineVersionInfoResourceImpl (assemblyFileName);
901 // runtime needs to value to embed it into the assembly
902 public_key = sn.PublicKey;
905 foreach (ModuleBuilder module in modules)
906 if (module != mainModule)
909 // Write out the main module at the end, because it needs to
910 // contain the hash of the other modules
913 if ((sn != null) && (sn.CanSign)) {
914 sn.Sign (System.IO.Path.Combine (this.AssemblyDir, assemblyFileName));
920 public void Save (string assemblyFileName)
922 Save (assemblyFileName, PortableExecutableKinds.ILOnly, ImageFileMachine.I386);
925 public void SetEntryPoint (MethodInfo entryMethod)
927 SetEntryPoint (entryMethod, PEFileKinds.ConsoleApplication);
930 public void SetEntryPoint (MethodInfo entryMethod, PEFileKinds fileKind)
932 if (entryMethod == null)
933 throw new ArgumentNullException ("entryMethod");
934 if (entryMethod.DeclaringType.Assembly != this)
935 throw new InvalidOperationException ("Entry method is not defined in the same assembly.");
937 entry_point = entryMethod;
941 public void SetCustomAttribute( CustomAttributeBuilder customBuilder)
943 if (customBuilder == null)
944 throw new ArgumentNullException ("customBuilder");
946 if (cattrs != null) {
947 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
948 cattrs.CopyTo (new_array, 0);
949 new_array [cattrs.Length] = customBuilder;
952 cattrs = new CustomAttributeBuilder [1];
953 cattrs [0] = customBuilder;
957 Only update the native list of custom attributes if we're adding one that is known to change dynamic execution behavior.
959 if (customBuilder.Ctor != null && customBuilder.Ctor.DeclaringType == typeof (System.Runtime.CompilerServices.RuntimeCompatibilityAttribute))
960 UpdateNativeCustomAttributes (this);
964 public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) {
966 throw new ArgumentNullException ("con");
967 if (binaryAttribute == null)
968 throw new ArgumentNullException ("binaryAttribute");
970 SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
973 private Exception not_supported () {
974 // Strange message but this is what MS.NET prints...
975 return new NotSupportedException ("The invoked member is not supported in a dynamic module.");
978 private void check_name_and_filename (string name, string fileName,
979 bool fileNeedsToExists) {
981 throw new ArgumentNullException ("name");
982 if (fileName == null)
983 throw new ArgumentNullException ("fileName");
984 if (name.Length == 0)
985 throw new ArgumentException ("Empty name is not legal.", "name");
986 if (fileName.Length == 0)
987 throw new ArgumentException ("Empty file name is not legal.", "fileName");
988 if (Path.GetFileName (fileName) != fileName)
989 throw new ArgumentException ("fileName '" + fileName + "' must not include a path.", "fileName");
991 // Resource files are created/searched under the assembly storage
993 string fullFileName = fileName;
995 fullFileName = Path.Combine (dir, fileName);
997 if (fileNeedsToExists && !File.Exists (fullFileName))
998 throw new FileNotFoundException ("Could not find file '" + fileName + "'");
1000 if (resources != null) {
1001 for (int i = 0; i < resources.Length; ++i) {
1002 if (resources [i].filename == fullFileName)
1003 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1004 if (resources [i].name == name)
1005 throw new ArgumentException ("Duplicate name '" + name + "'");
1009 if (modules != null) {
1010 for (int i = 0; i < modules.Length; ++i) {
1011 // Use fileName instead of fullFileName here
1012 if (!modules [i].IsTransient () && (modules [i].FileName == fileName))
1013 throw new ArgumentException ("Duplicate file name '" + fileName + "'");
1014 if (modules [i].Name == name)
1015 throw new ArgumentException ("Duplicate name '" + name + "'");
1020 private String create_assembly_version (String version) {
1021 String[] parts = version.Split ('.');
1022 int[] ver = new int [4] { 0, 0, 0, 0 };
1024 if ((parts.Length < 0) || (parts.Length > 4))
1025 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1027 for (int i = 0; i < parts.Length; ++i) {
1028 if (parts [i] == "*") {
1029 DateTime now = DateTime.Now;
1032 ver [2] = (now - new DateTime (2000, 1, 1)).Days;
1033 if (parts.Length == 3)
1034 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1038 ver [3] = (now.Second + (now.Minute * 60) + (now.Hour * 3600)) / 2;
1040 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1044 ver [i] = Int32.Parse (parts [i]);
1046 catch (FormatException) {
1047 throw new ArgumentException ("The version specified '" + version + "' is invalid");
1052 return ver [0] + "." + ver [1] + "." + ver [2] + "." + ver [3];
1055 private string GetCultureString (string str)
1057 return (str == "neutral" ? String.Empty : str);
1060 /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
1061 internal Type MakeGenericType (Type gtd, Type[] typeArguments)
1063 return new TypeBuilderInstantiation (gtd, typeArguments);
1066 void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
1068 throw new NotImplementedException ();
1071 void _AssemblyBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
1073 throw new NotImplementedException ();
1076 void _AssemblyBuilder.GetTypeInfoCount (out uint pcTInfo)
1078 throw new NotImplementedException ();
1081 void _AssemblyBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
1083 throw new NotImplementedException ();
1086 public override Type GetType (string name, bool throwOnError, bool ignoreCase)
1089 throw new ArgumentNullException (name);
1090 if (name.Length == 0)
1091 throw new ArgumentException ("name", "Name cannot be empty");
1093 var res = InternalGetType (null, name, throwOnError, ignoreCase);
1094 if (res is TypeBuilder) {
1096 throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name));
1102 public override Module GetModule (String name)
1105 throw new ArgumentNullException ("name");
1106 if (name.Length == 0)
1107 throw new ArgumentException ("Name can't be empty");
1109 if (modules == null)
1112 foreach (Module module in modules) {
1113 if (module.ScopeName == name)
1120 public override Module[] GetModules (bool getResourceModules)
1122 Module[] modules = GetModulesInternal ();
1124 if (!getResourceModules) {
1125 var result = new List<Module> (modules.Length);
1126 foreach (Module m in modules)
1127 if (!m.IsResource ())
1129 return result.ToArray ();
1134 public override AssemblyName GetName (bool copiedName)
1136 var aname = AssemblyName.Create (this, false);
1139 aname.SetPublicKey (sn.PublicKey);
1140 aname.SetPublicKeyToken (sn.PublicKeyToken);
1146 [MonoTODO ("This always returns an empty array")]
1147 public override AssemblyName[] GetReferencedAssemblies () {
1148 return GetReferencedAssemblies (this);
1151 public override Module[] GetLoadedModules (bool getResourceModules)
1153 return GetModules (getResourceModules);
1156 //FIXME MS has issues loading satelite assemblies from SRE
1157 public override Assembly GetSatelliteAssembly (CultureInfo culture)
1159 return GetSatelliteAssembly (culture, null, true);
1162 //FIXME MS has issues loading satelite assemblies from SRE
1163 public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
1165 return GetSatelliteAssembly (culture, version, true);
1168 public override Module ManifestModule {
1170 return GetManifestModule ();
1174 public override bool GlobalAssemblyCache {
1180 public override bool IsDynamic {
1181 get { return true; }
1184 public override bool Equals (object obj)
1186 return base.Equals (obj);
1189 public override int GetHashCode ()
1191 return base.GetHashCode ();
1194 public override bool IsDefined (Type attributeType, bool inherit)
1196 return base.IsDefined (attributeType, inherit);
1199 public override object[] GetCustomAttributes (bool inherit)
1201 return base.GetCustomAttributes (inherit);
1204 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
1206 return base.GetCustomAttributes (attributeType, inherit);
1209 public override string FullName {
1210 get { return base.FullName; }