The Labs \ Source Viewer \ SSCLI \ System.Reflection.Emit \ AssemblyBuilder

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Reflection.Emit
  16. {
  17.     using System;
  18.     using System.IO;
  19.     using System.Diagnostics.SymbolStore;
  20.     using System.Reflection;
  21.     using System.Diagnostics;
  22.     using System.Resources;
  23.     using System.Security.Permissions;
  24.     using System.Runtime.Remoting.Activation;
  25.     using CultureInfo = System.Globalization.CultureInfo;
  26.     using System.Runtime.Serialization;
  27.     using System.Security;
  28.     using System.Threading;
  29.     using System.Runtime.CompilerServices;
  30.     using System.Runtime.InteropServices;
  31.     using System.Runtime.Versioning;
  32.    
  33.     // AssemblyBuilder class.
  34.     // deliberately not [serializable]
  35.     [HostProtection(MayLeakOnAbort = true)]
  36.     [ClassInterface(ClassInterfaceType.None)]
  37.     [ComDefaultInterface(typeof(_AssemblyBuilder))]
  38.     [ComVisible(true)]
  39.     public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder
  40.     {
  41.        
  42. /**********************************************
  43.         *
  44.         * Defines a named dynamic module. It is an error to define multiple
  45.         * modules within an Assembly with the same name. This dynamic module is
  46.         * a transient module.
  47.         *
  48.         **********************************************/       
  49.         public ModuleBuilder DefineDynamicModule(string name)
  50.         {
  51.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  52.            
  53.             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  54.             return DefineDynamicModuleInternal(name, false, ref stackMark);
  55.         }
  56.        
  57.         // specify if emit symbol info or not
  58.         public ModuleBuilder DefineDynamicModule(string name, bool emitSymbolInfo)
  59.         {
  60.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  61.            
  62.             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  63.             return DefineDynamicModuleInternal(name, emitSymbolInfo, ref stackMark);
  64.         }
  65.        
  66.             // specify if emit symbol info or not
  67.         internal ModuleBuilder DefineDynamicModuleInternal(string name, bool emitSymbolInfo, ref StackCrawlMark stackMark)
  68.         {
  69.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + " )");
  70.            
  71.             BCLDebug.Assert(m_assemblyData != null, "m_assemblyData is null in DefineDynamicModuleInternal");
  72.            
  73.             if (name == null)
  74.                 throw new ArgumentNullException("name");
  75.             if (name.Length == 0)
  76.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
  77.             if (name[0] == '\0')
  78.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name");
  79.            
  80.             m_assemblyData.CheckNameConflict(name);
  81.            
  82.             // create the dynamic module
  83.             ModuleBuilder dynModule = nDefineDynamicModule(this, emitSymbolInfo, name, ref stackMark);
  84.             ISymbolWriter writer = null;
  85.            
  86.             if (emitSymbolInfo) {
  87.                 // create the default SymWriter
  88.                 Assembly assem = LoadISymWrapper();
  89.                 Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false);
  90.                 if (symWriter != null && !symWriter.IsVisible)
  91.                     symWriter = null;
  92.                
  93.                 if (symWriter == null) {
  94.                     // cannot find SymWriter
  95.                     throw new ExecutionEngineException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString(ResId.MissingType), "SymWriter"));
  96.                 }
  97.                 try {
  98.                     (new PermissionSet(PermissionState.Unrestricted)).Assert();
  99.                     writer = (ISymbolWriter)Activator.CreateInstance(symWriter);
  100.                 }
  101.                 finally {
  102.                     CodeAccessPermission.RevertAssert();
  103.                 }
  104.             }
  105.            
  106.             dynModule.Init(name, null, writer);
  107.             m_assemblyData.AddModule(dynModule);
  108.             return dynModule;
  109.         }
  110.        
  111.         private Assembly LoadISymWrapper()
  112.         {
  113.             if (m_assemblyData.m_ISymWrapperAssembly != null)
  114.                 return m_assemblyData.m_ISymWrapperAssembly;
  115.            
  116.             Assembly assem = Assembly.Load("ISymWrapper, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken);
  117.            
  118.             m_assemblyData.m_ISymWrapperAssembly = assem;
  119.             return assem;
  120.         }
  121.        
  122. /**********************************************
  123.         *
  124.         * Defines a named dynamic module. It is an error to define multiple
  125.         * modules within an Assembly with the same name. No symbol information
  126.         * will be emitted.
  127.         *
  128.         **********************************************/       
  129.         public ModuleBuilder DefineDynamicModule(string name, string fileName)
  130.         {
  131.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  132.            
  133.             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  134.            
  135.             // delegate to the next DefineDynamicModule
  136.             return DefineDynamicModuleInternal(name, fileName, false, ref stackMark);
  137.         }
  138.        
  139. /**********************************************
  140.         *
  141.         * Emit symbol information if emitSymbolInfo is true using the
  142.         * default symbol writer interface.
  143.         * An exception will be thrown if the assembly is transient.
  144.         *
  145.         **********************************************/       
  146.             // module name
  147.             // module file name
  148.         // specify if emit symbol info or not
  149.         public ModuleBuilder DefineDynamicModule(string name, string fileName, bool emitSymbolInfo)
  150.         {
  151.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  152.             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
  153.             return DefineDynamicModuleInternal(name, fileName, emitSymbolInfo, ref stackMark);
  154.         }
  155.        
  156.             // module name
  157.             // module file name
  158.             // specify if emit symbol info or not
  159.         // stack crawl mark used to find caller
  160.         private ModuleBuilder DefineDynamicModuleInternal(string name, string fileName, bool emitSymbolInfo, ref StackCrawlMark stackMark)
  161.         {
  162.             if (m_assemblyData.m_isSynchronized) {
  163.                 lock (m_assemblyData) {
  164.                     return DefineDynamicModuleInternalNoLock(name, fileName, emitSymbolInfo, ref stackMark);
  165.                 }
  166.             }
  167.             else {
  168.                 return DefineDynamicModuleInternalNoLock(name, fileName, emitSymbolInfo, ref stackMark);
  169.             }
  170.         }
  171.        
  172.         public override bool ReflectionOnly {
  173.             get { return base.ReflectionOnly; }
  174.         }
  175.        
  176.         internal void CheckContext(params Type[][] typess)
  177.         {
  178.             if (typess == null)
  179.                 return;
  180.            
  181.             foreach (Type[] types in typess)
  182.                 if (types != null)
  183.                     CheckContext(types);
  184.         }
  185.        
  186.         internal void CheckContext(params Type[] types)
  187.         {
  188.             if (types == null)
  189.                 return;
  190.            
  191.             foreach (Type type in types) {
  192.                 if (type == null || type.Module.Assembly == typeof(object).Module.Assembly)
  193.                     return;
  194.                 if (type.Module.Assembly.ReflectionOnly && !ReflectionOnly)
  195.                     throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arugment_EmitMixedContext1"), type.AssemblyQualifiedName));
  196.                
  197.                 if (!type.Module.Assembly.ReflectionOnly && ReflectionOnly)
  198.                     throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arugment_EmitMixedContext2"), type.AssemblyQualifiedName));
  199.             }
  200.         }
  201.        
  202.             // module name
  203.             // module file name
  204.             // specify if emit symbol info or not
  205.         // stack crawl mark used to find caller
  206.         private ModuleBuilder DefineDynamicModuleInternalNoLock(string name, string fileName, bool emitSymbolInfo, ref StackCrawlMark stackMark)
  207.         {
  208.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + ", " + fileName + ", " + emitSymbolInfo + " )");
  209.             if (m_assemblyData.m_access == AssemblyBuilderAccess.Run) {
  210.                 // Error! You cannot define a persistable module within a transient data.
  211.                 throw new NotSupportedException(Environment.GetResourceString("Argument_BadPersistableModuleInTransientAssembly"));
  212.             }
  213.            
  214.             if (m_assemblyData.m_isSaved == true) {
  215.                 // assembly has been saved before!
  216.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotAlterAssembly"));
  217.             }
  218.            
  219.             if (name == null)
  220.                 throw new ArgumentNullException("name");
  221.             if (name.Length == 0)
  222.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
  223.             if (name[0] == '\0')
  224.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name");
  225.            
  226.             if (fileName == null)
  227.                 throw new ArgumentNullException("fileName");
  228.             if (fileName.Length == 0)
  229.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName");
  230.             if (!String.Equals(fileName, Path.GetFileName(fileName)))
  231.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
  232.            
  233.             m_assemblyData.CheckNameConflict(name);
  234.             m_assemblyData.CheckFileNameConflict(fileName);
  235.            
  236.             // ecall to create the dynamic module
  237.             ModuleBuilder dynModule = nDefineDynamicModule(this, emitSymbolInfo, fileName, ref stackMark);
  238.             ISymbolWriter writer = null;
  239.            
  240.             if (emitSymbolInfo) {
  241.                 // create the default SymWriter
  242.                 Assembly assem = LoadISymWrapper();
  243.                 Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false);
  244.                 if (symWriter != null && !symWriter.IsVisible)
  245.                     symWriter = null;
  246.                
  247.                 if (symWriter == null) {
  248.                     // cannot find SymWriter
  249.                     throw new ExecutionEngineException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("MissingType"), "SymWriter"));
  250.                 }
  251.                 try {
  252.                     (new PermissionSet(PermissionState.Unrestricted)).Assert();
  253.                     writer = (ISymbolWriter)Activator.CreateInstance(symWriter);
  254.                 }
  255.                 finally {
  256.                     CodeAccessPermission.RevertAssert();
  257.                 }
  258.                
  259.             }
  260.            
  261.             // initialize the dynamic module's managed side information
  262.             dynModule.Init(name, fileName, writer);
  263.             m_assemblyData.AddModule(dynModule);
  264.             return dynModule;
  265.         }
  266.        
  267.        
  268. /**********************************************
  269.         *
  270.         * Define stand alone managed resource for Assembly
  271.         *
  272.         **********************************************/       
  273.         [ResourceExposure(ResourceScope.Machine)]
  274.         [ResourceConsumption(ResourceScope.Machine)]
  275.         public IResourceWriter DefineResource(string name, string description, string fileName)
  276.         {
  277.             return DefineResource(name, description, fileName, ResourceAttributes.Public);
  278.         }
  279.        
  280. /**********************************************
  281.         *
  282.         * Define stand alone managed resource for Assembly
  283.         *
  284.         **********************************************/       
  285.         [ResourceExposure(ResourceScope.Machine)]
  286.         [ResourceConsumption(ResourceScope.Machine)]
  287.         public IResourceWriter DefineResource(string name, string description, string fileName, ResourceAttributes attribute)
  288.         {
  289.             if (m_assemblyData.m_isSynchronized) {
  290.                 lock (m_assemblyData) {
  291.                     return DefineResourceNoLock(name, description, fileName, attribute);
  292.                 }
  293.             }
  294.             else {
  295.                 return DefineResourceNoLock(name, description, fileName, attribute);
  296.             }
  297.         }
  298.        
  299.         [ResourceExposure(ResourceScope.Machine)]
  300.         [ResourceConsumption(ResourceScope.Machine)]
  301.         private IResourceWriter DefineResourceNoLock(string name, string description, string fileName, ResourceAttributes attribute)
  302.         {
  303.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  304.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineResource( " + name + ", " + fileName + ")");
  305.            
  306.             if (name == null)
  307.                 throw new ArgumentNullException("name");
  308.             if (name.Length == 0)
  309.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name);
  310.             if (fileName == null)
  311.                 throw new ArgumentNullException("fileName");
  312.             if (fileName.Length == 0)
  313.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName");
  314.             if (!String.Equals(fileName, Path.GetFileName(fileName)))
  315.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
  316.            
  317.             m_assemblyData.CheckResNameConflict(name);
  318.             m_assemblyData.CheckFileNameConflict(fileName);
  319.            
  320.             ResourceWriter resWriter;
  321.             string fullFileName;
  322.            
  323.             if (m_assemblyData.m_strDir == null) {
  324.                 // If assembly directory is null, use current directory
  325.                 fullFileName = Path.Combine(Environment.CurrentDirectory, fileName);
  326.                 resWriter = new ResourceWriter(fullFileName);
  327.             }
  328.             else {
  329.                 // Form the full path given the directory provided by user
  330.                 fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName);
  331.                 resWriter = new ResourceWriter(fullFileName);
  332.             }
  333.             // get the full path
  334.             fullFileName = Path.GetFullPath(fullFileName);
  335.            
  336.             // retrieve just the file name
  337.             fileName = Path.GetFileName(fullFileName);
  338.            
  339.             m_assemblyData.AddResWriter(new ResWriterData(resWriter, null, name, fileName, fullFileName, attribute));
  340.             return resWriter;
  341.         }
  342.        
  343.        
  344. /**********************************************
  345.         *
  346.         * Add an existing resource file to the Assembly
  347.         *
  348.         **********************************************/       
  349.         [ResourceExposure(ResourceScope.Machine)]
  350.         [ResourceConsumption(ResourceScope.Machine)]
  351.         public void AddResourceFile(string name, string fileName)
  352.         {
  353.             AddResourceFile(name, fileName, ResourceAttributes.Public);
  354.         }
  355.        
  356. /**********************************************
  357.         *
  358.         * Add an existing resource file to the Assembly
  359.         *
  360.         **********************************************/       
  361.         [ResourceExposure(ResourceScope.Machine)]
  362.         [ResourceConsumption(ResourceScope.Machine)]
  363.         public void AddResourceFile(string name, string fileName, ResourceAttributes attribute)
  364.         {
  365.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  366.             if (m_assemblyData.m_isSynchronized) {
  367.                 lock (m_assemblyData) {
  368.                     AddResourceFileNoLock(name, fileName, attribute);
  369.                 }
  370.             }
  371.             else {
  372.                 AddResourceFileNoLock(name, fileName, attribute);
  373.             }
  374.         }
  375.        
  376.         [ResourceExposure(ResourceScope.Machine)]
  377.         [ResourceConsumption(ResourceScope.Machine)]
  378.         private void AddResourceFileNoLock(string name, string fileName, ResourceAttributes attribute)
  379.         {
  380.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.AddResourceFile( " + name + ", " + fileName + ")");
  381.            
  382.             if (name == null)
  383.                 throw new ArgumentNullException("name");
  384.             if (name.Length == 0)
  385.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name);
  386.             if (fileName == null)
  387.                 throw new ArgumentNullException("fileName");
  388.             if (fileName.Length == 0)
  389.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), fileName);
  390.             if (!String.Equals(fileName, Path.GetFileName(fileName)))
  391.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
  392.            
  393.             m_assemblyData.CheckResNameConflict(name);
  394.             m_assemblyData.CheckFileNameConflict(fileName);
  395.            
  396.             string fullFileName;
  397.            
  398.             if (m_assemblyData.m_strDir == null) {
  399.                 // If assembly directory is null, use current directory
  400.                 fullFileName = Path.Combine(Environment.CurrentDirectory, fileName);
  401.             }
  402.             else {
  403.                 // Form the full path given the directory provided by user
  404.                 fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName);
  405.             }
  406.            
  407.             // get the full path
  408.             fullFileName = Path.GetFullPath(fullFileName);
  409.            
  410.             // retrieve just the file name
  411.             fileName = Path.GetFileName(fullFileName);
  412.            
  413.             if (File.Exists(fullFileName) == false)
  414.                 throw new FileNotFoundException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("IO.FileNotFound_FileName"), fileName), fileName);
  415.             m_assemblyData.AddResWriter(new ResWriterData(null, null, name, fileName, fullFileName, attribute));
  416.         }
  417.        
  418.         // Returns the names of all the resources
  419.         public override string[] GetManifestResourceNames()
  420.         {
  421.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  422.         }
  423.        
  424.         public override FileStream GetFile(string name)
  425.         {
  426.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  427.         }
  428.        
  429.         public override FileStream[] GetFiles(bool getResourceModules)
  430.         {
  431.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  432.         }
  433.        
  434.         public override Stream GetManifestResourceStream(Type type, string name)
  435.         {
  436.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  437.         }
  438.        
  439.         public override Stream GetManifestResourceStream(string name)
  440.         {
  441.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  442.         }
  443.        
  444.         public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
  445.         {
  446.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  447.         }
  448.        
  449.         public override string Location {
  450.             get {
  451.                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  452.             }
  453.         }
  454.        
  455.         public override string ImageRuntimeVersion {
  456.             get { return RuntimeEnvironment.GetSystemVersion(); }
  457.         }
  458.        
  459.         public override string CodeBase {
  460.             get {
  461.                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
  462.             }
  463.         }
  464.        
  465.        
  466.        
  467.        
  468.        
  469. /**********************************************
  470.         *
  471.         * return a dynamic module with the specified name.
  472.         *
  473.         **********************************************/       
  474.         // the name of module for the look up
  475.         public ModuleBuilder GetDynamicModule(string name)
  476.         {
  477.             if (m_assemblyData.m_isSynchronized) {
  478.                 lock (m_assemblyData) {
  479.                     return GetDynamicModuleNoLock(name);
  480.                 }
  481.             }
  482.             else {
  483.                 return GetDynamicModuleNoLock(name);
  484.             }
  485.         }
  486.        
  487.         // the name of module for the look up
  488.         private ModuleBuilder GetDynamicModuleNoLock(string name)
  489.         {
  490.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.GetDynamicModule( " + name + " )");
  491.             if (name == null)
  492.                 throw new ArgumentNullException("name");
  493.             if (name.Length == 0)
  494.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
  495.            
  496.             int size = m_assemblyData.m_moduleBuilderList.Count;
  497.             for (int i = 0; i < size; i++) {
  498.                 ModuleBuilder moduleBuilder = (ModuleBuilder)m_assemblyData.m_moduleBuilderList[i];
  499.                 if (moduleBuilder.m_moduleData.m_strModuleName.Equals(name)) {
  500.                     return moduleBuilder;
  501.                 }
  502.             }
  503.             return null;
  504.         }
  505.        
  506. /**********************************************
  507.         *
  508.         * Setting the entry point if the assembly builder is building
  509.         * an exe.
  510.         *
  511.         **********************************************/       
  512.         public void SetEntryPoint(MethodInfo entryMethod)
  513.         {
  514.             SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication);
  515.         }
  516.             // entry method for the assembly. We use this to determine the entry module
  517.         // file kind for the assembly.
  518.         public void SetEntryPoint(MethodInfo entryMethod, PEFileKinds fileKind)
  519.         {
  520.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  521.             if (m_assemblyData.m_isSynchronized) {
  522.                 lock (m_assemblyData) {
  523.                     SetEntryPointNoLock(entryMethod, fileKind);
  524.                 }
  525.             }
  526.             else {
  527.                 SetEntryPointNoLock(entryMethod, fileKind);
  528.             }
  529.         }
  530.        
  531.             // entry method for the assembly. We use this to determine the entry module
  532.         // file kind for the assembly.
  533.         private void SetEntryPointNoLock(MethodInfo entryMethod, PEFileKinds fileKind)
  534.         {
  535.            
  536.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.SetEntryPoint");
  537.             if (entryMethod == null)
  538.                 throw new ArgumentNullException("entryMethod");
  539.            
  540.             //
  541.             //
  542.             Module tmpModule = entryMethod.Module;
  543.             if (!(tmpModule is ModuleBuilder && this.Equals(tmpModule.Assembly)))
  544.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EntryMethodNotDefinedInAssembly"));
  545.             m_assemblyData.m_entryPointModule = (ModuleBuilder)tmpModule;
  546.             m_assemblyData.m_entryPointMethod = entryMethod;
  547.             m_assemblyData.m_peFileKind = fileKind;
  548.             m_assemblyData.m_entryPointModule.SetEntryPoint(entryMethod);
  549.         }
  550.        
  551.        
  552.         // Override the EntryPoint method on Assembly.
  553.         public override MethodInfo EntryPoint {
  554.             get { return m_assemblyData.m_entryPointMethod; }
  555.         }
  556.        
  557. /**********************************************
  558.         * Use this function if client decides to form the custom attribute blob themselves
  559.         **********************************************/       
  560.         [System.Runtime.InteropServices.ComVisible(true)]
  561.         public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
  562.         {
  563.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  564.             if (con == null)
  565.                 throw new ArgumentNullException("con");
  566.             if (binaryAttribute == null)
  567.                 throw new ArgumentNullException("binaryAttribute");
  568.            
  569.             ModuleBuilder inMemoryAssemblyModule;
  570.             inMemoryAssemblyModule = m_assemblyData.GetInMemoryAssemblyModule();
  571.                 // This is the AssemblyDef token
  572.                 // pass in the in-memory assembly module
  573.             TypeBuilder.InternalCreateCustomAttribute(AssemblyBuilderData.m_tkAssembly, inMemoryAssemblyModule.GetConstructorToken(con).Token, binaryAttribute, inMemoryAssemblyModule, false, typeof(System.Diagnostics.DebuggableAttribute) == con.DeclaringType);
  574.            
  575.             // Track the CA for persistence
  576.             if (m_assemblyData.m_access == AssemblyBuilderAccess.Run) {
  577.                 return;
  578.             }
  579.            
  580.             // tracking the CAs for persistence
  581.             m_assemblyData.AddCustomAttribute(con, binaryAttribute);
  582.         }
  583.        
  584. /**********************************************
  585.         * Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
  586.         **********************************************/       
  587.         public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
  588.         {
  589.             CodeAccessPermission.DemandInternal(PermissionType.ReflectionEmit);
  590.             if (customBuilder == null) {
  591.                 throw new ArgumentNullException("customBuilder");
  592.             }
  593.            
  594.             ModuleBuilder inMemoryAssemblyModule;
  595.             inMemoryAssemblyModule = m_assemblyData.GetInMemoryAssemblyModule();
  596.             customBuilder.CreateCustomAttribute(inMemoryAssemblyModule, AssemblyBuilderData.m_tkAssembly);
  597.             // This is the AssemblyDef token
  598.             // Track the CA for persistence
  599.             if (m_assemblyData.m_access == AssemblyBuilderAccess.Run) {
  600.                 return;
  601.             }
  602.             m_assemblyData.AddCustomAttribute(customBuilder);
  603.         }
  604.        
  605.        
  606. /**********************************************
  607.         *
  608.         * Saves the assembly to disk. Also saves all dynamic modules defined
  609.         * in this dynamic assembly. Assembly file name can be the same as one of
  610.         * the module's name. If so, assembly info is stored within that module.
  611.         * Assembly file name can be different from all of the modules underneath. In
  612.         * this case, assembly is stored stand alone.
  613.         *
  614.         **********************************************/       
  615.        
  616.         [ResourceExposure(ResourceScope.Machine)]
  617.         [ResourceConsumption(ResourceScope.Machine)]
  618.         // assembly file name
  619.         public void Save(string assemblyFileName)
  620.         {
  621.             Save(assemblyFileName, System.Reflection.PortableExecutableKinds.ILOnly, System.Reflection.ImageFileMachine.I386);
  622.         }
  623.        
  624.         [ResourceExposure(ResourceScope.Machine)]
  625.         [ResourceConsumption(ResourceScope.Machine)]
  626.         public void Save(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
  627.         {
  628.             if (m_assemblyData.m_isSynchronized) {
  629.                 lock (m_assemblyData) {
  630.                     SaveNoLock(assemblyFileName, portableExecutableKind, imageFileMachine);
  631.                 }
  632.             }
  633.             else {
  634.                 SaveNoLock(assemblyFileName, portableExecutableKind, imageFileMachine);
  635.             }
  636.         }
  637.        
  638.         [ResourceExposure(ResourceScope.Machine)]
  639.         [ResourceConsumption(ResourceScope.Machine)]
  640.         private void SaveNoLock(string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
  641.         {
  642.             int i;
  643.             int size;
  644.             Type type;
  645.             TypeBuilder typeBuilder;
  646.             ModuleBuilder modBuilder;
  647.             string strModFileName;
  648.             ModuleBuilder assemblyModule;
  649.             ResWriterData tempRes;
  650.             int[] tkAttrs = null;
  651.             int[] tkAttrs2 = null;
  652.             ModuleBuilder onDiskAssemblyModule;
  653.            
  654.             BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.Save( " + assemblyFileName + " )");
  655.            
  656.             string tmpVersionFile = null;
  657.            
  658.             try {
  659.                 if (m_assemblyData.m_iCABuilder != 0)
  660.                     tkAttrs = new int[m_assemblyData.m_iCABuilder];
  661.                 if (m_assemblyData.m_iCAs != 0)
  662.                     tkAttrs2 = new int[m_assemblyData.m_iCAs];
  663.                
  664.                 if (m_assemblyData.m_isSaved == true) {
  665.                     // assembly has been saved before!
  666.                     throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString(ResId.InvalidOperation_AssemblyHasBeenSaved), nGetSimpleName()));
  667.                 }
  668.                
  669.                 if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) != AssemblyBuilderAccess.Save) {
  670.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CantSaveTransientAssembly"));
  671.                 }
  672.                
  673.                 if (assemblyFileName == null)
  674.                     throw new ArgumentNullException("assemblyFileName");
  675.                 if (assemblyFileName.Length == 0)
  676.                     throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "assemblyFileName");
  677.                 if (!String.Equals(assemblyFileName, Path.GetFileName(assemblyFileName)))
  678.                     throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "assemblyFileName");
  679.                
  680.                 // Check if assembly info is supposed to be stored with one of the module files.
  681.                 assemblyModule = m_assemblyData.FindModuleWithFileName(assemblyFileName);
  682.                
  683.                 if (assemblyModule != null) {
  684.                     m_assemblyData.SetOnDiskAssemblyModule(assemblyModule);
  685.                 }
  686.                
  687.                 // If assembly is to be stored alone, then no file name should conflict with it.
  688.                 // This check will ensure resource file names are different assembly file name.
  689.                 //
  690.                 if (assemblyModule == null) {
  691.                     m_assemblyData.CheckFileNameConflict(assemblyFileName);
  692.                    
  693.                 }
  694.                
  695.                 if (m_assemblyData.m_strDir == null) {
  696.                     // set it to current directory
  697.                     m_assemblyData.m_strDir = Environment.CurrentDirectory;
  698.                 }
  699.                 else if (Directory.Exists(m_assemblyData.m_strDir) == false) {
  700.                     throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_InvalidDirectory"), m_assemblyData.m_strDir));
  701.                 }
  702.                
  703.                 // after this point, assemblyFileName is the full path name.
  704.                 assemblyFileName = Path.Combine(m_assemblyData.m_strDir, assemblyFileName);
  705.                 assemblyFileName = Path.GetFullPath(assemblyFileName);
  706.                
  707.                 // Check caller has the right to create the assembly file itself.
  708.                 new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, assemblyFileName).Demand();
  709.                
  710.                 // 1. setup/create the IMetaDataAssemblyEmit for the on disk version
  711.                 if (assemblyModule != null) {
  712.                     // prepare saving CAs on assembly def. We need to introduce the MemberRef for
  713.                     // the CA's type first of all. This is for the case the we have embedded manifest.
  714.                     // We need to introduce these MRs before we call PreSave where we will snap
  715.                     // into a ondisk metadata. If we do it after this, the ondisk metadata will
  716.                     // not contain the proper MRs.
  717.                     //
  718.                     for (i = 0; i < m_assemblyData.m_iCABuilder; i++) {
  719.                         tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk(assemblyModule);
  720.                     }
  721.                     for (i = 0; i < m_assemblyData.m_iCAs; i++) {
  722.                         tkAttrs2[i] = assemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token;
  723.                     }
  724.                     assemblyModule.PreSave(assemblyFileName, portableExecutableKind, imageFileMachine);
  725.                 }
  726.                 nPrepareForSavingManifestToDisk(assemblyModule);
  727.                
  728.                 // This function will return the embedded manifest module, an already exposed ModuleBuilder
  729.                 // created by user, or make the stand alone manifest module exposed through managed code.
  730.                 //
  731.                 onDiskAssemblyModule = m_assemblyData.GetOnDiskAssemblyModule();
  732.                
  733.                
  734.                 if (assemblyModule == null) {
  735.                    
  736.                     // This is for introducing the MRs for CA's type. This case is for stand alone
  737.                     // manifest. We need to wait till nPrepareForSavingManifestToDisk is called.
  738.                     // That will trigger the creation of the on-disk stand alone manifest module.
  739.                     //
  740.                     for (i = 0; i < m_assemblyData.m_iCABuilder; i++) {
  741.                         tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk(onDiskAssemblyModule);
  742.                     }
  743.                     for (i = 0; i < m_assemblyData.m_iCAs; i++) {
  744.                         tkAttrs2[i] = onDiskAssemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token;
  745.                     }
  746.                 }
  747.                
  748.                 // 2. save all of the persistable modules contained by this AssemblyBuilder except the module that is going to contain
  749.                 // Assembly information
  750.                 //
  751.                 // 3. create the file list in the manifest and track the file token. If it is embedded assembly,
  752.                 // the assembly file should not be on the file list.
  753.                 //
  754.                 size = m_assemblyData.m_moduleBuilderList.Count;
  755.                 for (i = 0; i < size; i++) {
  756.                     ModuleBuilder mBuilder = (ModuleBuilder)m_assemblyData.m_moduleBuilderList[i];
  757.                     if (mBuilder.IsTransient() == false && mBuilder != assemblyModule) {
  758.                         strModFileName = mBuilder.m_moduleData.m_strFileName;
  759.                         if (m_assemblyData.m_strDir != null) {
  760.                             strModFileName = Path.Combine(m_assemblyData.m_strDir, strModFileName);
  761.                             strModFileName = Path.GetFullPath(strModFileName);
  762.                         }
  763.                        
  764.                         // Check caller has the right to create the Module file itself.
  765.                         new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, strModFileName).Demand();
  766.                        
  767.                         mBuilder.m_moduleData.m_tkFile = nSaveToFileList(mBuilder.m_moduleData.m_strFileName);
  768.                         mBuilder.PreSave(strModFileName, portableExecutableKind, imageFileMachine);
  769.                         mBuilder.Save(strModFileName, false, portableExecutableKind, imageFileMachine);
  770.                        
  771.                         // Cannot set the hash value when creating the file since the file token
  772.                         // is needed to created the entries for the embedded resources in the
  773.                         // module and the resources need to be there before you figure the hash.
  774.                         nSetHashValue(mBuilder.m_moduleData.m_tkFile, strModFileName);
  775.                     }
  776.                 }
  777.                
  778.                 // 4. Add the public ComType
  779.                 for (i = 0; i < m_assemblyData.m_iPublicComTypeCount; i++) {
  780.                     type = m_assemblyData.m_publicComTypeList[i];
  781.                     if (type is System.RuntimeType) {
  782.                         modBuilder = m_assemblyData.FindModuleWithName(type.Module.m_moduleData.m_strModuleName);
  783.                         if (modBuilder != assemblyModule)
  784.                             DefineNestedComType(type, modBuilder.m_moduleData.m_tkFile, type.MetadataTokenInternal);
  785.                     }
  786.                     else {
  787.                         // Could assert that "type" is a TypeBuilder, but next statement throws if it isn't.
  788.                         typeBuilder = (TypeBuilder)type;
  789.                         modBuilder = (ModuleBuilder)type.Module;
  790.                         if (modBuilder != assemblyModule)
  791.                             DefineNestedComType(type, modBuilder.m_moduleData.m_tkFile, typeBuilder.MetadataTokenInternal);
  792.                     }
  793.                 }
  794.                
  795.                 // 5. write AssemblyDef's CAs
  796.                 for (i = 0; i < m_assemblyData.m_iCABuilder; i++) {
  797.                         // This is the AssemblyDef token
  798.                     m_assemblyData.m_CABuilders[i].CreateCustomAttribute(onDiskAssemblyModule, AssemblyBuilderData.m_tkAssembly, tkAttrs[i], true);
  799.                 }
  800.                
  801.                 for (i = 0; i < m_assemblyData.m_iCAs; i++) {
  802.                         // This is the AssemblyDef token
  803.                         // pass in the in-memory assembly module
  804.                     TypeBuilder.InternalCreateCustomAttribute(AssemblyBuilderData.m_tkAssembly, tkAttrs2[i], m_assemblyData.m_CABytes[i], onDiskAssemblyModule, true);
  805.                 }
  806.                
  807.                 // 6. write security permission requests to the manifest.
  808.                 if (m_assemblyData.m_RequiredPset != null || m_assemblyData.m_OptionalPset != null || m_assemblyData.m_RefusedPset != null) {
  809.                     // Translate sets into internal encoding (uses standard binary serialization).
  810.                     byte[] required = null;
  811.                     byte[] optional = null;
  812.                     byte[] refused = null;
  813.                     if (m_assemblyData.m_RequiredPset != null)
  814.                         required = m_assemblyData.m_RequiredPset.EncodeXml();
  815.                     if (m_assemblyData.m_OptionalPset != null)
  816.                         optional = m_assemblyData.m_OptionalPset.EncodeXml();
  817.                     if (m_assemblyData.m_RefusedPset != null)
  818.                         refused = m_assemblyData.m_RefusedPset.EncodeXml();
  819.                     nSavePermissionRequests(required, optional, refused);
  820.                 }
  821.                
  822.                 // 7. Save the stand alone managed resources
  823.                 size = m_assemblyData.m_resWriterList.Count;
  824.                 for (i = 0; i < size; i++) {
  825.                     tempRes = null;
  826.                    
  827.                     try {
  828.                         tempRes = (ResWriterData)m_assemblyData.m_resWriterList[i];
  829.                        
  830.                         // If the user added an existing resource to the manifest, the
  831.                         // corresponding ResourceWriter will be null.
  832.                         if (tempRes.m_resWriter != null)
  833.                             // Check caller has the right to create the Resource file itself.
  834.                             new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, tempRes.m_strFullFileName).Demand();
  835.                     }
  836.                     finally {
  837.                         if (tempRes != null && tempRes.m_resWriter != null)
  838.                             tempRes.m_resWriter.Close();
  839.                     }
  840.                    
  841.                     // Add entry to manifest for this stand alone resource
  842.                     nAddStandAloneResource(tempRes.m_strName, tempRes.m_strFileName, tempRes.m_strFullFileName, (int)tempRes.m_attribute);
  843.                 }
  844.                
  845.                 // Save now!!
  846.                 if (assemblyModule == null) {
  847.                    
  848.                    
  849.                     // Stand alone manifest
  850.                     if (m_assemblyData.m_entryPointModule != null) {
  851.                         nSaveManifestToDisk(assemblyFileName, m_assemblyData.m_entryPointModule.m_moduleData.m_tkFile, (int)m_assemblyData.m_peFileKind, (int)portableExecutableKind, (int)imageFileMachine);
  852.                     }
  853.                     else {
  854.                         nSaveManifestToDisk(assemblyFileName, 0, (int)m_assemblyData.m_peFileKind, (int)portableExecutableKind, (int)imageFileMachine);
  855.                     }
  856.                 }
  857.                 else {
  858.                     // embedded manifest
  859.                    
  860.                     // If the module containing the entry point is not the manifest file, we need to
  861.                     // let the manifest file point to the module which contains the entry point.
  862.                     //
  863.                     //
  864.                     //
  865.                     //
  866.                     if (m_assemblyData.m_entryPointModule != null && m_assemblyData.m_entryPointModule != assemblyModule)
  867.                         assemblyModule.m_EntryPoint = new MethodToken(m_assemblyData.m_entryPointModule.m_moduleData.m_tkFile);
  868.                     assemblyModule.Save(assemblyFileName, true, portableExecutableKind, imageFileMachine);
  869.                 }
  870.                 m_assemblyData.m_isSaved = true;
  871.             }
  872.             finally {
  873.                 if (tmpVersionFile != null) {
  874.                     // Delete file.
  875.                     System.IO.File.Delete(tmpVersionFile);
  876.                 }
  877.             }
  878.         }
  879.        
  880.        
  881.        
  882.         // Get an array of all the public types defined in this assembly
  883.         public override Type[] GetExportedTypes()
  884.         {
  885.             throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
  886.         }
  887.        
  888.         internal bool IsPersistable()
  889.         {
  890.             if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) == AssemblyBuilderAccess.Save)
  891.                 return true;
  892.             else
  893.                 return false;
  894.         }
  895.        
  896. /**********************************************
  897.         *
  898.         * Internal helper to walk the nested type hierachy
  899.         *
  900.         **********************************************/       
  901.         private int DefineNestedComType(Type type, int tkResolutionScope, int tkTypeDef)
  902.         {
  903.             Type enclosingType = type.DeclaringType;
  904.             if (enclosingType == null) {
  905.                 return nSaveExportedType(type.FullName, tkResolutionScope, tkTypeDef, type.Attributes);
  906.             }
  907.             else {
  908.                 tkResolutionScope = DefineNestedComType(enclosingType, tkResolutionScope, tkTypeDef);
  909.             }
  910.             return nSaveExportedType(type.FullName, tkResolutionScope, tkTypeDef, type.Attributes);
  911.         }
  912.        
  913. /**********************************************
  914.         *
  915.         * Private methods
  916.         *
  917.         **********************************************/       
  918.        
  919. /**********************************************
  920.         * Make a private constructor so these cannot be constructed externally.
  921.         * @internonly
  922.         **********************************************/       
  923.         private AssemblyBuilder()
  924.         {
  925.         }
  926.        
  927.         void _AssemblyBuilder.GetTypeInfoCount(out uint pcTInfo)
  928.         {
  929.             throw new NotImplementedException();
  930.         }
  931.        
  932.         void _AssemblyBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
  933.         {
  934.             throw new NotImplementedException();
  935.         }
  936.        
  937.         void _AssemblyBuilder.GetIDsOfNames(        [In()]
  938. ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  939.         {
  940.             throw new NotImplementedException();
  941.         }
  942.        
  943.         void _AssemblyBuilder.Invoke(uint dispIdMember,         [In()]
  944. ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  945.         {
  946.             throw new NotImplementedException();
  947.         }
  948.     }
  949. }

Developer Fusion