We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

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

  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.    
  18.     using System;
  19.     using System.Runtime.Remoting.Activation;
  20.     using System.Reflection;
  21.     using System.Security;
  22.     using System.Security.Permissions;
  23.     using System.Diagnostics;
  24.     using System.Runtime.InteropServices;
  25.     using System.Runtime.CompilerServices;
  26.     using ArrayList = System.Collections.ArrayList;
  27.     using CultureInfo = System.Globalization.CultureInfo;
  28.     using System.Threading;
  29.    
  30.    
  31.     [Serializable()]
  32.     [System.Runtime.InteropServices.ComVisible(true)]
  33.     public enum PackingSize
  34.     {
  35.         Unspecified = 0,
  36.         Size1 = 1,
  37.         Size2 = 2,
  38.         Size4 = 4,
  39.         Size8 = 8,
  40.         Size16 = 16,
  41.         Size32 = 32,
  42.         Size64 = 64,
  43.         Size128 = 128
  44.     }
  45.    
  46.    
  47.     [HostProtection(MayLeakOnAbort = true)]
  48.     [ClassInterface(ClassInterfaceType.None)]
  49.     [ComDefaultInterface(typeof(_TypeBuilder))]
  50.     [System.Runtime.InteropServices.ComVisible(true)]
  51.     public sealed class TypeBuilder : Type, _TypeBuilder
  52.     {
  53.         #region Declarations
  54.         internal class CustAttr
  55.         {
  56.             private ConstructorInfo m_con;
  57.             private byte[] m_binaryAttribute;
  58.             private CustomAttributeBuilder m_customBuilder;
  59.            
  60.             public CustAttr(ConstructorInfo con, byte[] binaryAttribute)
  61.             {
  62.                 if (con == null)
  63.                     throw new ArgumentNullException("con");
  64.                
  65.                 if (binaryAttribute == null)
  66.                     throw new ArgumentNullException("binaryAttribute");
  67.                
  68.                 m_con = con;
  69.                 m_binaryAttribute = binaryAttribute;
  70.             }
  71.            
  72.             public CustAttr(CustomAttributeBuilder customBuilder)
  73.             {
  74.                 if (customBuilder == null)
  75.                     throw new ArgumentNullException("customBuilder");
  76.                
  77.                 m_customBuilder = customBuilder;
  78.             }
  79.            
  80.             public void Bake(ModuleBuilder module, int token)
  81.             {
  82.                 if (m_customBuilder == null) {
  83.                     TypeBuilder.InternalCreateCustomAttribute(token, module.GetConstructorToken(m_con).Token, m_binaryAttribute, module, false);
  84.                 }
  85.                 else {
  86.                     m_customBuilder.CreateCustomAttribute(module, token);
  87.                 }
  88.             }
  89.         }
  90.         #endregion
  91.        
  92.         #region Public Static Methods
  93.         public static MethodInfo GetMethod(Type type, MethodInfo method)
  94.         {
  95.             if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
  96.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
  97.            
  98.             // The following checks establishes invariants that more simply put require type to be generic and
  99.             // method to be a generic method definition declared on the generic type definition of type.
  100.             // To create generic method G<Foo>.M<Bar> these invariants require that G<Foo>.M<S> be created by calling
  101.             // this function followed by MakeGenericMethod on the resulting MethodInfo to finally get G<Foo>.M<Bar>.
  102.             // We could also allow G<T>.M<Bar> to be created before G<Foo>.M<Bar> (BindGenParm followed by this method)
  103.             // if we wanted to but that just complicates things so these checks are designed to prevent that scenario.
  104.            
  105.             if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
  106.                 throw new ArgumentException(Environment.GetResourceString("Argument_NeedGenericMethodDefinition"), "method");
  107.            
  108.             if (method.DeclaringType == null || !method.DeclaringType.IsGenericTypeDefinition)
  109.                 throw new ArgumentException(Environment.GetResourceString("Argument_MethodNeedGenericDeclaringType"), "method");
  110.            
  111.             if (type.GetGenericTypeDefinition() != method.DeclaringType)
  112.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMethodDeclaringType"), "type");
  113.            
  114.             // The following converts from Type or TypeBuilder of G<T> to TypeBuilderInstantiation G<T>. These types
  115.             // both logically represent the same thing. The runtime displays a similar convention by having
  116.             // G<M>.M() be encoded by a typeSpec whose parent is the typeDef for G<M> and whose instantiation is also G<M>.
  117.             if (type.IsGenericTypeDefinition)
  118.                 type = type.MakeGenericType(type.GetGenericArguments());
  119.            
  120.             if (!(type is TypeBuilderInstantiation))
  121.                 throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
  122.            
  123.             return MethodOnTypeBuilderInstantiation.GetMethod(method, type as TypeBuilderInstantiation);
  124.         }
  125.         public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor)
  126.         {
  127.             if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
  128.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
  129.            
  130.             if (!constructor.DeclaringType.IsGenericTypeDefinition)
  131.                 throw new ArgumentException(Environment.GetResourceString("Argument_ConstructorNeedGenericDeclaringType"), "constructor");
  132.            
  133.             if (!(type is TypeBuilderInstantiation))
  134.                 throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
  135.            
  136.             // TypeBuilder G<T> ==> TypeBuilderInstantiation G<T>
  137.             if (type is TypeBuilder && type.IsGenericTypeDefinition)
  138.                 type = type.MakeGenericType(type.GetGenericArguments());
  139.            
  140.             if (type.GetGenericTypeDefinition() != constructor.DeclaringType)
  141.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorDeclaringType"), "type");
  142.            
  143.             return ConstructorOnTypeBuilderInstantiation.GetConstructor(constructor, type as TypeBuilderInstantiation);
  144.         }
  145.         public static FieldInfo GetField(Type type, FieldInfo field)
  146.         {
  147.             if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
  148.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
  149.            
  150.             if (!field.DeclaringType.IsGenericTypeDefinition)
  151.                 throw new ArgumentException(Environment.GetResourceString("Argument_FieldNeedGenericDeclaringType"), "field");
  152.            
  153.             if (!(type is TypeBuilderInstantiation))
  154.                 throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
  155.            
  156.             // TypeBuilder G<T> ==> TypeBuilderInstantiation G<T>
  157.             if (type is TypeBuilder && type.IsGenericTypeDefinition)
  158.                 type = type.MakeGenericType(type.GetGenericArguments());
  159.            
  160.             if (type.GetGenericTypeDefinition() != field.DeclaringType)
  161.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFieldDeclaringType"), "type");
  162.            
  163.             return FieldOnTypeBuilderInstantiation.GetField(field, type as TypeBuilderInstantiation);
  164.         }
  165.         #endregion
  166.        
  167.         #region Public Const
  168.         public const int UnspecifiedTypeSize = 0;
  169.         #endregion
  170.        
  171.         #region Private Static FCalls
  172.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  173.         private static extern void InternalSetParentType(int tdTypeDef, int tkParent, Module module);
  174.        
  175.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  176.         private static extern void InternalAddInterfaceImpl(int tdTypeDef, int tkInterface, Module module);
  177.         #endregion
  178.        
  179.         #region Internal Static FCalls
  180.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  181.         static internal extern int InternalDefineMethod(int handle, string name, byte[] signature, int sigLength, MethodAttributes attributes, Module module);
  182.        
  183.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  184.         static internal extern int InternalDefineMethodSpec(int handle, byte[] signature, int sigLength, Module module);
  185.        
  186.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  187.         static internal extern int InternalDefineField(int handle, string name, byte[] signature, int sigLength, FieldAttributes attributes, Module module);
  188.        
  189.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  190.         static internal extern void InternalSetMethodIL(int methodHandle, bool isInitLocals, byte[] body, byte[] LocalSig, int sigLength, int maxStackSize, int numExceptions, __ExceptionInstance[] exceptions, int[] tokenFixups, int[] rvaFixups,
  191.         Module module);
  192.        
  193.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  194.         static internal extern void InternalCreateCustomAttribute(int tkAssociate, int tkConstructor, byte[] attr, Module module, bool toDisk, bool updateCompilerFlags);
  195.        
  196.         static internal void InternalCreateCustomAttribute(int tkAssociate, int tkConstructor, byte[] attr, Module module, bool toDisk)
  197.         {
  198.             byte[] localAttr = null;
  199.            
  200.             if (attr != null) {
  201.                 localAttr = new byte[attr.Length];
  202.                 Array.Copy(attr, localAttr, attr.Length);
  203.             }
  204.             TypeBuilder.InternalCreateCustomAttribute(tkAssociate, tkConstructor, localAttr, module, toDisk, false);
  205.         }
  206.        
  207.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  208.         static internal extern void InternalSetPInvokeData(Module module, string DllName, string name, int token, int linkType, int linkFlags);
  209.        
  210.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  211.         static internal extern int InternalDefineProperty(Module module, int handle, string name, int attributes, byte[] signature, int sigLength, int notifyChanging, int notifyChanged);
  212.        
  213.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  214.         static internal extern int InternalDefineEvent(Module module, int handle, string name, int attributes, int tkEventType);
  215.        
  216.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  217.         static internal extern void InternalDefineMethodSemantics(Module module, int tkAssociation, MethodSemanticsAttributes semantics, int tkMethod);
  218.        
  219.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  220.         static internal extern void InternalDefineMethodImpl(ModuleBuilder module, int tkType, int tkBody, int tkDecl);
  221.        
  222.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  223.         static internal extern void InternalSetMethodImpl(Module module, int tkMethod, MethodImplAttributes MethodImplAttributes);
  224.        
  225.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  226.         static internal extern int InternalSetParamInfo(Module module, int tkMethod, int iSequence, ParameterAttributes iParamAttributes, string strParamName);
  227.        
  228.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  229.         static internal extern int InternalGetTokenFromSig(Module module, byte[] signature, int sigLength);
  230.        
  231.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  232.         static internal extern void InternalSetFieldOffset(Module module, int fdToken, int iOffset);
  233.        
  234.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  235.         static internal extern void InternalSetClassLayout(Module module, int tdToken, PackingSize iPackingSize, int iTypeSize);
  236.        
  237.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  238.         static internal extern void InternalSetMarshalInfo(Module module, int tk, byte[] ubMarshal, int ubSize);
  239.        
  240.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  241.         static internal extern void InternalSetConstantValue(Module module, int tk, ref Variant var);
  242.        
  243.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  244.         static internal extern void InternalAddDeclarativeSecurity(Module module, int parent, SecurityAction action, byte[] blob);
  245.         #endregion
  246.        
  247.         #region Internal\Private Static Members
  248.         private static bool IsPublicComType(Type type)
  249.         {
  250.             // Internal Helper to determine if a type should be added to ComType table.
  251.             // A top level type should be added if it is Public.
  252.             // A nested type should be added if the top most enclosing type is Public
  253.             // and all the enclosing types are NestedPublic
  254.            
  255.             Type enclosingType = type.DeclaringType;
  256.             if (enclosingType != null) {
  257.                 if (IsPublicComType(enclosingType)) {
  258.                     if ((type.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic) {
  259.                         return true;
  260.                     }
  261.                 }
  262.             }
  263.             else {
  264.                 if ((type.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) {
  265.                     return true;
  266.                 }
  267.             }
  268.            
  269.             return false;
  270.         }
  271.        
  272.         static internal bool IsTypeEqual(Type t1, Type t2)
  273.         {
  274.             // Maybe we are lucky that they are equal in the first place
  275.             if (t1 == t2)
  276.                 return true;
  277.             TypeBuilder tb1 = null;
  278.             TypeBuilder tb2 = null;
  279.             Type runtimeType1 = null;
  280.             Type runtimeType2 = null;
  281.            
  282.             // set up the runtimeType and TypeBuilder type corresponding to t1 and t2
  283.             if (t1 is TypeBuilder) {
  284.                 tb1 = (TypeBuilder)t1;
  285.                 // This will be null if it is not baked.
  286.                 runtimeType1 = tb1.m_runtimeType;
  287.             }
  288.             else {
  289.                 runtimeType1 = t1;
  290.             }
  291.            
  292.             if (t2 is TypeBuilder) {
  293.                 tb2 = (TypeBuilder)t2;
  294.                 // This will be null if it is not baked.
  295.                 runtimeType2 = tb2.m_runtimeType;
  296.             }
  297.             else {
  298.                 runtimeType2 = t2;
  299.             }
  300.            
  301.             // If the type builder view is eqaul then it is equal
  302.             if (tb1 != null && tb2 != null && tb1 == tb2)
  303.                 return true;
  304.            
  305.             // if the runtimetype view is eqaul than it is equal
  306.             if (runtimeType1 != null && runtimeType2 != null && runtimeType1 == runtimeType2)
  307.                 return true;
  308.            
  309.             return false;
  310.         }
  311.        
  312.         static internal void SetConstantValue(Module module, int tk, Type destType, object value)
  313.         {
  314.             // This is a helper function that is used by ParameterBuilder, PropertyBuilder,
  315.             // and FieldBuilder to validate a default value and save it in the meta-data.
  316.            
  317.             if (value == null) {
  318.                 if (destType.IsValueType)
  319.                     throw new ArgumentException(Environment.GetResourceString("Argument_ConstantNull"));
  320.             }
  321.             else {
  322.                 // client is going to set non-null constant value
  323.                 Type type = value.GetType();
  324.                
  325.                 // The default value on the enum typed field/parameter is the underlying type.
  326.                 if (destType.IsEnum == false) {
  327.                     if (destType != type)
  328.                         throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
  329.                    
  330.                     switch (Type.GetTypeCode(type)) {
  331.                         case TypeCode.Boolean:
  332.                         case TypeCode.Char:
  333.                         case TypeCode.SByte:
  334.                         case TypeCode.Byte:
  335.                         case TypeCode.Int16:
  336.                         case TypeCode.UInt16:
  337.                         case TypeCode.Int32:
  338.                         case TypeCode.UInt32:
  339.                         case TypeCode.Int64:
  340.                         case TypeCode.UInt64:
  341.                         case TypeCode.Single:
  342.                         case TypeCode.Double:
  343.                         case TypeCode.Decimal:
  344.                         case TypeCode.String:
  345.                             break;
  346.                         default:
  347.                            
  348.                             {
  349.                                 if (type != typeof(System.DateTime))
  350.                                     throw new ArgumentException(Environment.GetResourceString("Argument_ConstantNotSupported"));
  351.                                 break;
  352.                             }
  353.                             break;
  354.                        
  355.                     }
  356.                 }
  357.                 else {
  358.                     // The constant value supplied should match the underlying type of the enum
  359.                     if (destType.UnderlyingSystemType != type)
  360.                         throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
  361.                 }
  362.             }
  363.            
  364.             // pass the variant by reference to avoid woes with passing valuetypes into FCALLs
  365.             Variant var = new Variant(value);
  366.            
  367.             InternalSetConstantValue(module, tk, ref var);
  368.         }
  369.        
  370.         #endregion
  371.        
  372.         #region Private Data Members
  373.         internal ArrayList m_ca;
  374.         internal MethodBuilder m_currentMethod;
  375.         private TypeToken m_tdType;
  376.         private ModuleBuilder m_module;
  377.         internal string m_strName;
  378.         private string m_strNameSpace;
  379.         private string m_strFullQualName;
  380.         private Type m_typeParent;
  381.         private Type[] m_typeInterfaces;
  382.         internal TypeAttributes m_iAttr;
  383.         internal GenericParameterAttributes m_genParamAttributes;
  384.         internal ArrayList m_listMethods;
  385.         private int m_constructorCount;
  386.         private int m_iTypeSize;
  387.         private PackingSize m_iPackingSize;
  388.         private TypeBuilder m_DeclaringType;
  389.         private Type m_underlyingSystemType;
  390.         // set when user calls UnderlyingSystemType on TypeBuilder if TypeBuilder is an Enum
  391.         internal bool m_isHiddenGlobalType;
  392.         internal bool m_isHiddenType;
  393.         internal bool m_hasBeenCreated;
  394.         internal RuntimeType m_runtimeType;
  395.        
  396.         private int m_genParamPos;
  397.         private GenericTypeParameterBuilder[] m_inst;
  398.         private bool m_bIsGenParam;
  399.         private bool