diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index b782d0ef86e321..42f73ece562cbe 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -840,6 +840,12 @@ internal override void ResolveToken(int token, out IntPtr typeHandle, out IntPtr #endregion } + /// + /// Provides support for alternative ways to generate the Microsoft intermediate language (MSIL) and metadata for a dynamic method, including methods for creating tokens and for inserting the code, exception handling, and local variable signature blobs. + /// + /// + /// For more information about this API, see Supplemental API remarks for DynamicILInfo. + /// public class DynamicILInfo { #region Private Data Members @@ -878,15 +884,45 @@ internal void GetCallableMethod(RuntimeModule module, DynamicMethod dm) #endregion #region Public ILGenerator Methods + /// + /// Gets the dynamic method whose body is generated by the current instance. + /// + /// A object representing the dynamic method for which the current object is generating code. + /// + /// A object is always associated with a dynamic method. The purpose of the class is to provide another way of inserting the MSIL stream, exception handling, and local variable signature into a dynamic method, for developers who want to generate MSIL without using the class. + /// public DynamicMethod DynamicMethod => m_method; internal DynamicScope DynamicScope => m_scope; + /// + /// Sets the code body of the associated dynamic method. + /// + /// An array that contains the MSIL stream. + /// The maximum number of items on the operand stack when the method is executing. + /// + /// No validity checks are performed on the MSIL stream. + /// Calling this method a second time replaces the first MSIL stream with the second. + /// Generating your own metadata and MSIL requires familiarity with the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics" and "Partition III: CIL Instruction Set". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// public void SetCode(byte[]? code, int maxStackSize) { m_code = (code != null) ? (byte[])code.Clone() : []; m_maxStackSize = maxStackSize; } + /// + /// Sets the code body of the associated dynamic method. + /// + /// A pointer to a byte array containing the MSIL stream. + /// The number of bytes in the MSIL stream. + /// The maximum number of items on the operand stack when the method is executing. + /// + /// No validity checks are performed on the MSIL stream. + /// Calling this method a second time replaces the first MSIL stream with the second. + /// Generating your own metadata and MSIL requires familiarity with the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics" and "Partition III: CIL Instruction Set." For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// + /// is and is greater than 0. + /// is less than 0. [CLSCompliant(false)] public unsafe void SetCode(byte* code, int codeSize, int maxStackSize) { @@ -898,11 +934,28 @@ public unsafe void SetCode(byte* code, int codeSize, int maxStackSize) m_maxStackSize = maxStackSize; } + /// + /// Sets the exception metadata for the associated dynamic method. + /// + /// An array that contains the exception metadata. + /// + /// The exception metadata for a method defines the location and size of all `try`, `catch`, `finally`, filter, and fault blocks. For information on the layout of this metadata, see the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// public void SetExceptions(byte[]? exceptions) { m_exceptions = (exceptions != null) ? (byte[])exceptions.Clone() : []; } + /// + /// Sets the exception metadata for the associated dynamic method. + /// + /// A pointer to a byte array containing the exception metadata. + /// The number of bytes of exception metadata. + /// + /// The exception metadata for a method defines the location and size of all `try`, `catch`, `finally`, filter, and fault blocks. For information on the layout of this metadata, see the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics" and "Partition III: CIL Instruction Set". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// + /// is and is greater than 0. + /// is less than 0. [CLSCompliant(false)] public unsafe void SetExceptions(byte* exceptions, int exceptionsSize) { @@ -914,11 +967,30 @@ public unsafe void SetExceptions(byte* exceptions, int exceptionsSize) m_exceptions = new Span(exceptions, exceptionsSize).ToArray(); } + /// + /// Sets the local variable signature that describes the layout of local variables for the associated dynamic method. + /// + /// An array that contains the layout of local variables for the associated . + /// + /// The local variable signature describes the layout of a method's local variables. To simplify construction of the local variable signature, use the ( in Visual Basic) SignatureHelper.GetLocalVarSigHelper method to get a for the local signature. + /// For information on local variable signatures, see the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// public void SetLocalSignature(byte[]? localSignature) { m_localSignature = (localSignature != null) ? (byte[])localSignature.Clone() : []; } + /// + /// Sets the local variable signature that describes the layout of local variables for the associated dynamic method. + /// + /// An array that contains the layout of local variables for the associated . + /// The number of bytes in the signature. + /// + /// The local variable signature describes the layout of a method's local variables. To simplify construction of the local variable signature, use the ( in Visual Basic) SignatureHelper.GetLocalVarSigHelper method to get a for the local signature. + /// For information on local variable signatures, see the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// + /// is and is greater than 0. + /// is less than 0. [CLSCompliant(false)] public unsafe void SetLocalSignature(byte* localSignature, int signatureSize) { @@ -931,34 +1003,99 @@ public unsafe void SetLocalSignature(byte* localSignature, int signatureSize) #endregion #region Public Scope Methods + /// + /// Gets a token, valid in the scope of the current , representing a method to be accessed from the associated dynamic method. + /// + /// The method to be accessed. + /// A token that can be used as the operand of an MSIL instruction that accesses methods, such as or , in the scope of the current object. + /// + /// You must obtain a token for any method that will be accessed by the dynamic method associated with the current object. Use the Type.GetMethod method to get a for the method you want to access, and then use the property to get the . + /// For a method that belongs to a generic type, use the method overload and specify a for the generic type. + /// public int GetTokenFor(RuntimeMethodHandle method) { return DynamicScope.GetTokenFor(method); } + /// + /// Gets a token, valid in the scope of the current , representing a dynamic method to be called from the associated method. + /// + /// The dynamic method to call. + /// A token that can be embedded in the MSIL stream for the associated dynamic method, as the target of an MSIL instruction. + /// + /// The token returned by this method overload allows you to call a dynamic method from the dynamic method associated with the current object. To call the associated dynamic method recursively, pass the value of the property. + /// public int GetTokenFor(DynamicMethod method) { return DynamicScope.GetTokenFor(method); } + /// + /// Gets a token, valid in the scope of the current , representing a method on a generic type. + /// + /// The method. + /// The generic type the method belongs to. + /// A token that can be used as the operand of an MSIL instruction that accesses methods, such as or , in the scope of the current object. + /// + /// You must obtain a token for any method that will be called by the dynamic method associated with the current object. Use the Type.GetMethod method to get a for the method you want to call, and then use the property to get the . + /// public int GetTokenFor(RuntimeMethodHandle method, RuntimeTypeHandle contextType) { return DynamicScope.GetTokenFor(method, contextType); } + /// + /// Gets a token, valid in the scope of the current , representing a field to be accessed from the associated dynamic method. + /// + /// The field to be accessed. + /// A token that can be used as the operand of an MSIL instruction that accesses fields, in the scope of the current object. + /// + /// You must obtain a token for any field that will be accessed by the dynamic method associated with the current object. Use the Type.GetField method to get a for the field you want to access, then use the property to get the . + /// public int GetTokenFor(RuntimeFieldHandle field) { return DynamicScope.GetTokenFor(field); } + /// + /// Gets a token, valid in the scope of the current , representing a field to be accessed from the associated dynamic method; the field is on the specified generic type. + /// + /// The field to be accessed. + /// The generic type the field belongs to. + /// A token that can be used as the operand of an MSIL instruction that accesses fields in the scope of the current object. + /// + /// You must obtain a token for any field that will be accessed by the dynamic method associated with the current object. Use the Type.GetField method to get a for the field you want to access, and then use the property to get the . + /// public int GetTokenFor(RuntimeFieldHandle field, RuntimeTypeHandle contextType) { return DynamicScope.GetTokenFor(field, contextType); } + /// + /// Gets a token, valid in the scope of the current , representing a type to be used in the associated dynamic method. + /// + /// The type to be used. + /// A token that can be used as the operand of an MSIL instruction that requires a type, in the scope of the current object. + /// + /// The token returned by this method overload allows you to define a local variable type, and emit MSIL to create an instance of a type in the dynamic method associated with the current object. + /// To get a representing a type, use the property. + /// public int GetTokenFor(RuntimeTypeHandle type) { return DynamicScope.GetTokenFor(type); } + /// + /// Gets a token, valid in the scope of the current , representing a string literal to be used in the associated dynamic method. + /// + /// The string to be used. + /// A token that can be used as the operand of an MSIL instruction that requires a string, in the scope of the current object. public int GetTokenFor(string literal) { return DynamicScope.GetTokenFor(literal); } + /// + /// Gets a token, valid in the scope of the current , representing the signature for the associated dynamic method. + /// + /// An array that contains the signature. + /// A token that can be embedded in the metadata and the MSIL stream for the associated dynamic method. + /// + /// For information on signature blobs, see the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics". For more information, see ECMA 335 Common Language Infrastructure (CLI). + /// public int GetTokenFor(byte[] signature) { return DynamicScope.GetTokenFor(signature); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs index abdb8be14b27a3..6df897b2c78e51 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs @@ -41,9 +41,30 @@ public sealed partial class DynamicMethod : MethodInfo // Delegate and method creation // + /// + /// Completes the dynamic method and creates a delegate that can be used to execute it. + /// + /// A delegate type whose signature matches that of the dynamic method. + /// A delegate of the specified type, which can be used to execute the dynamic method. + /// The dynamic method has no method body. + /// has the wrong number of parameters or the wrong parameter types. + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.CreateDelegate. + /// public sealed override Delegate CreateDelegate(Type delegateType) => CreateDelegate(delegateType, target: null); + /// + /// Completes the dynamic method and creates a delegate that can be used to execute it, specifying the delegate type and an object the delegate is bound to. + /// + /// A delegate type whose signature matches that of the dynamic method, minus the first parameter. + /// An object the delegate is bound to. Must be of the same type as the first parameter of the dynamic method. + /// A delegate of the specified type, which can be used to execute the dynamic method with the specified target object. + /// The dynamic method has no method body. + /// has the wrong number of parameters or the wrong parameter types. + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.CreateDelegate. + /// public sealed override Delegate CreateDelegate(Type delegateType, object? target) { if (_restrictedSkipVisibility) @@ -114,6 +135,21 @@ Signature LazyCreateSignature() } } + /// + /// Invokes the dynamic method using the specified parameters, under the constraints of the specified binder, with the specified culture information. + /// + /// This parameter is ignored for dynamic methods, because they are static. Specify . + /// A bitwise combination of values. + /// A object that enables the binding, coercion of argument types, invocation of members, and retrieval of objects through reflection. If is , the default binder is used. + /// An argument list. This is an array of arguments with the same number, order, and type as the parameters of the method to be invoked. If there are no parameters this parameter should be . + /// An instance of used to govern the coercion of types. If this is , the for the current thread is used. + /// An containing the return value of the invoked method. + /// The number of elements in does not match the number of parameters in the dynamic method. + /// The dynamic method contains unverifiable code. + /// The dynamic method has no method body. + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.Invoke. + /// public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) @@ -143,6 +179,13 @@ Signature LazyCreateSignature() return retValue; } + /// + /// Returns a object that can be used to generate a method body from metadata tokens, scopes, and Microsoft intermediate language (MSIL) streams. + /// + /// A object that can be used to generate a method body from metadata tokens, scopes, and MSIL streams. + /// + /// The class is provided to support unmanaged code generation. + /// public DynamicILInfo GetDynamicILInfo() { if (_dynamicILInfo == null) @@ -154,6 +197,14 @@ public DynamicILInfo GetDynamicILInfo() return _dynamicILInfo; } + /// + /// Returns a Microsoft intermediate language (MSIL) generator for the method with the specified MSIL stream size. + /// + /// The size of the MSIL stream, in bytes. + /// An object for the method. + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.GetILGenerator. + /// public ILGenerator GetILGenerator(int streamSize) { if (_ilGenerator == null) diff --git a/src/libraries/System.Private.CoreLib/samples/System/Reflection/Emit/DynamicMethod.Examples.cs b/src/libraries/System.Private.CoreLib/samples/System/Reflection/Emit/DynamicMethod.Examples.cs new file mode 100644 index 00000000000000..b59fdfef083958 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/samples/System/Reflection/Emit/DynamicMethod.Examples.cs @@ -0,0 +1,143 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// This file contains code examples for XML documentation. +// The examples are referenced by the DynamicMethod class documentation using #region names. + +#pragma warning disable CS8321 // Local function is declared but never used + +using System; +using System.Reflection; +using System.Reflection.Emit; + +namespace System.Reflection.Emit.Examples +{ + internal static class DynamicMethodExamples + { + private static void Examples() + { + // Note: 'hello' represents a DynamicMethod instance used in the examples below + + #region Name + // Display the name specified when the dynamic method was created. + // Note that the name can be blank. + Console.WriteLine("\r\nName: {0}", hello.Name); + #endregion + + #region DeclaringType + // Display the declaring type, which is always null for dynamic + // methods. + if (hello.DeclaringType == null) + { + Console.WriteLine("\r\nDeclaringType is always null for dynamic methods."); + } + else + { + Console.WriteLine("DeclaringType: {0}", hello.DeclaringType); + } + #endregion + + #region ReflectedType + // For dynamic methods, the reflected type is always null. + if (hello.ReflectedType == null) + { + Console.WriteLine("\r\nReflectedType is null."); + } + else + { + Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType); + } + #endregion + + #region Module + // Display the module specified when the dynamic method was created. + Console.WriteLine("\r\nModule: {0}", hello.Module); + #endregion + + #region Attributes + // Display MethodAttributes for the dynamic method, set when + // the dynamic method was created. + Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes); + #endregion + + #region CallingConvention + // Display the calling convention of the dynamic method, set when the + // dynamic method was created. + Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention); + #endregion + + #region GetParameters + // Display parameter information. + ParameterInfo[] parameters = hello.GetParameters(); + Console.WriteLine("\r\nParameters: name, type, ParameterAttributes"); + foreach( ParameterInfo p in parameters ) + { + Console.WriteLine("\t{0}, {1}, {2}", + p.Name, p.ParameterType, p.Attributes); + } + #endregion + + #region ReturnType + // If the method has no return type, ReturnType is System.Void. + Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType); + #endregion + + #region ReturnTypeCustomAttributes + // ReturnTypeCustomAttributes returns an ICustomAttributeProvider + // that can be used to enumerate the custom attributes of the + // return value. At present, there is no way to set such custom + // attributes, so the list is empty. + if (hello.ReturnType == typeof(void)) + { + Console.WriteLine("The method has no return type."); + } + else + { + ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes; + object[] returnAttributes = caProvider.GetCustomAttributes(true); + if (returnAttributes.Length == 0) + { + Console.WriteLine("\r\nThe return type has no custom attributes."); + } + else + { + Console.WriteLine("\r\nThe return type has the following custom attributes:"); + foreach( object attr in returnAttributes ) + { + Console.WriteLine("\t{0}", attr.ToString()); + } + } + } + #endregion + + #region DefineParameter + // Add parameter information to the dynamic method. (This is not + // necessary, but can be useful for debugging.) For each parameter, + // identified by position, supply the parameter attributes and a + // parameter name. + hello.DefineParameter(1, ParameterAttributes.In, "message"); + hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn"); + #endregion + + #region ToString + Console.WriteLine("\r\nToString: {0}", hello.ToString()); + #endregion + + #region InitLocals + // Display the default value for InitLocals. + if (hello.InitLocals) + { + Console.Write("\r\nThis method contains verifiable code."); + } + else + { + Console.Write("\r\nThis method contains unverifiable code."); + } + Console.WriteLine(" (InitLocals = {0})", hello.InitLocals); + #endregion + } + + // Placeholder for the DynamicMethod variable used in examples + private static DynamicMethod hello = null!; + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index 60b3586d375986..49af5f7b110079 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -10,6 +10,12 @@ namespace System.Reflection.Emit { + /// + /// Defines and represents a dynamic method that can be compiled, executed, and discarded. Discarded methods are available for garbage collection. + /// + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// public sealed partial class DynamicMethod : MethodInfo { // The context when the method was created. We use this to do the RestrictedMemberAccess checks. @@ -25,6 +31,18 @@ public sealed partial class DynamicMethod : MethodInfo // class initialization (ctor and init) // + /// + /// Initializes an anonymously hosted dynamic method, specifying the method name, return type, and parameter types. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// An element of is or . + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -41,6 +59,19 @@ public DynamicMethod(string name, true); } + /// + /// Initializes an anonymously hosted dynamic method, specifying the method name, return type, parameter types, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method, with this restriction: the trust level of the assemblies that contain those types and members must be equal to or less than the trust level of the call stack that emits the dynamic method; otherwise, . + /// An element of is or . + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -58,6 +89,23 @@ public DynamicMethod(string name, true); } + /// + /// Creates a dynamic method that is global to a module, specifying the method name, return type, parameter types, and module. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A representing the module with which the dynamic method is to be logically associated. + /// An element of is or . + /// -or- + /// is a module that provides anonymous hosting for dynamic methods. + /// is . + /// -or- + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -77,6 +125,24 @@ public DynamicMethod(string name, false); } + /// + /// Creates a dynamic method that is global to a module, specifying the method name, return type, parameter types, module, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A representing the module with which the dynamic method is to be logically associated. + /// to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method; otherwise, . + /// An element of is or . + /// -or- + /// is a module that provides anonymous hosting for dynamic methods. + /// is . + /// -or- + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -97,6 +163,30 @@ public DynamicMethod(string name, false); } + /// + /// Creates a dynamic method that is global to a module, specifying the method name, attributes, calling convention, return type, parameter types, module, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A bitwise combination of values that specifies the attributes of the dynamic method. The only combination allowed is and . + /// The calling convention for the dynamic method. Must be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A representing the module with which the dynamic method is to be logically associated. + /// to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method; otherwise, . + /// An element of is or . + /// -or- + /// is a module that provides anonymous hosting for dynamic methods. + /// is . + /// -or- + /// is . + /// is a combination of flags other than and . + /// -or- + /// is not . + /// -or- + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, MethodAttributes attributes, @@ -119,6 +209,23 @@ public DynamicMethod(string name, false); } + /// + /// Creates a dynamic method, specifying the method name, return type, parameter types, and the type with which the dynamic method is logically associated. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A with which the dynamic method is logically associated. The dynamic method has access to all members of the type. + /// An element of is or . + /// -or- + /// is an interface, an array, an open generic type, or a type parameter of a generic type or method. + /// is . + /// -or- + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -138,6 +245,24 @@ public DynamicMethod(string name, false); } + /// + /// Creates a dynamic method, specifying the method name, return type, parameter types, the type with which the dynamic method is logically associated, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A with which the dynamic method is logically associated. The dynamic method has access to all members of the type. + /// to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method; otherwise, . + /// An element of is or . + /// -or- + /// is an interface, an array, an open generic type, or a type parameter of a generic type or method. + /// is . + /// -or- + /// is . + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, Type? returnType, @@ -158,6 +283,30 @@ public DynamicMethod(string name, false); } + /// + /// Creates a dynamic method, specifying the method name, attributes, calling convention, return type, parameter types, the type with which the dynamic method is logically associated, and whether just-in-time (JIT) visibility checks should be skipped for types and members accessed by the Microsoft intermediate language (MSIL) of the dynamic method. + /// + /// The name of the dynamic method. This can be a zero-length string, but it cannot be . + /// A bitwise combination of values that specifies the attributes of the dynamic method. The only combination allowed is and . + /// The calling convention for the dynamic method. Must be . + /// A object that specifies the return type of the dynamic method, or if the method has no return type. + /// An array of objects specifying the types of the parameters of the dynamic method, or if the method has no parameters. + /// A with which the dynamic method is logically associated. The dynamic method has access to all members of the type. + /// to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method; otherwise, . + /// An element of is or . + /// -or- + /// is an interface, an array, an open generic type, or a type parameter of a generic type or method. + /// is . + /// -or- + /// is . + /// is a combination of flags other than and . + /// -or- + /// is not . + /// -or- + /// .NET Framework and .NET Core versions older than 2.1: is a type for which returns . + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod. + /// [RequiresDynamicCode("Creating a DynamicMethod requires dynamic code.")] public DynamicMethod(string name, MethodAttributes attributes, @@ -297,6 +446,16 @@ private void Init(string name, // MethodInfo api. // + /// + /// Returns a string representation of the dynamic method. + /// + /// A string representation of the dynamic method, showing the return type, name, and parameter types. + /// + /// + /// + /// + /// The signature includes only types and the method name, if any. Parameter names are not included. + /// public override string ToString() { var sbName = new ValueStringBuilder(MethodNameBufferSize); @@ -312,37 +471,168 @@ public override string ToString() return sbName.ToString(); } + /// + /// Gets the name of the dynamic method. + /// + /// The name of the dynamic method. + /// + /// + /// + /// + /// It is not necessary to name dynamic methods. + /// public override string Name => _name; + /// + /// Gets the type that declares the dynamic method. + /// + /// Always for dynamic methods. + /// + /// + /// + /// + /// This property always returns for dynamic methods. Even when a dynamic method is logically associated with a type, it is not declared by the type. + /// public override Type? DeclaringType => null; + /// + /// Gets the class object that was used to obtain the instance of the dynamic method. + /// + /// Always for dynamic methods. + /// + /// + /// + /// + /// This property always returns for dynamic methods. + /// public override Type? ReflectedType => null; + /// + /// Gets the module associated with the dynamic method. + /// + /// The associated with the dynamic method. + /// + /// + /// + /// + /// If a module was specified when the dynamic method was created, this property returns that module. If a type was specified as the owner when the dynamic method was created, this property returns the module that contains that type. + /// public override Module Module => _module; // we cannot return a MethodHandle because we cannot track it via GC so this method is off limits + /// + /// Not supported for dynamic methods. + /// + /// Not supported for dynamic methods. + /// Always thrown. The of a dynamic method is not supported. public override RuntimeMethodHandle MethodHandle => throw new InvalidOperationException(SR.InvalidOperation_NotAllowedInDynamicMethod); + /// + /// Gets the attributes specified when the dynamic method was created. + /// + /// A bitwise combination of the values representing the attributes for the method. + /// + /// + /// + /// + /// Currently, the method attributes for a dynamic method are always and . + /// public override MethodAttributes Attributes => _attributes; + /// + /// Gets the calling convention specified when the dynamic method was created. + /// + /// One of the values that indicates the calling convention of the method. + /// + /// + /// + /// + /// Currently, the calling convention for a dynamic method is always . + /// public override CallingConventions CallingConvention => _callingConvention; + /// + /// Returns the base definition for the dynamic method. + /// + /// Always returns this dynamic method. + /// + /// This method always returns the current object. + /// public override MethodInfo GetBaseDefinition() => this; + /// + /// Returns an array of objects representing the parameters of the dynamic method. + /// + /// An array of objects representing the parameters of the dynamic method, or an empty array if the method has no parameters. + /// + /// + /// + /// + /// The objects returned by this method are for information only. Use the method to set or change the characteristics of the parameters. + /// public override ParameterInfo[] GetParameters() => GetParametersAsSpan().ToArray(); internal override ReadOnlySpan GetParametersAsSpan() => LoadParameters(); + /// + /// Returns the implementation flags for the method. + /// + /// A bitwise combination of values representing the implementation flags for the method. + /// + /// Currently, method implementation attributes for dynamic methods are always and . + /// public override MethodImplAttributes GetMethodImplementationFlags() => MethodImplAttributes.IL | MethodImplAttributes.NoInlining; + /// + /// Gets a value that indicates whether the dynamic method is security-critical. + /// + /// + /// .NET (Core): for all dynamic methods. + /// .NET Framework: if the current dynamic method is security-critical or security-safe-critical; if it is transparent. + /// + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.IsSecurityCritical. + /// public override bool IsSecurityCritical => true; + /// + /// Gets a value that indicates whether the dynamic method is security-safe-critical. + /// + /// + /// .NET (Core): for all dynamic methods. + /// .NET Framework: if the dynamic method is safe-critical; if it is critical or transparent. + /// + /// + /// For .NET Framework remarks about security transparency, see the property. + /// public override bool IsSecuritySafeCritical => false; + /// + /// Gets a value that indicates whether the dynamic method is security-transparent. + /// + /// + /// .NET (Core): for all dynamic methods. + /// .NET Framework: if the dynamic method is transparent; otherwise, . + /// + /// + /// For .NET Framework remarks about security transparency, see the property. + /// public override bool IsSecurityTransparent => false; + /// + /// Returns an array of all custom attributes defined on the dynamic method. + /// + /// The type of attribute to search for. Only attributes that are assignable to this type are returned. + /// This parameter is ignored for dynamic methods, because they do not support inheritance. + /// An array of custom attributes defined on the dynamic method. If no attributes of the specified type are defined, an empty array is returned. + /// is not a . + /// is . + /// + /// For dynamic methods, specifying for has no effect, because the method is not declared in a type. + /// Custom attributes are not currently supported on dynamic methods. The only attribute returned is ; you can get the method implementation flags more easily using the method. + /// public override object[] GetCustomAttributes(Type attributeType, bool inherit) { ArgumentNullException.ThrowIfNull(attributeType); @@ -359,12 +649,32 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) return result; } + /// + /// Returns an array of all custom attributes defined on the dynamic method. + /// + /// This parameter is ignored for dynamic methods, because they do not support inheritance. + /// An array of all custom attributes defined on the dynamic method. + /// + /// For dynamic methods, specifying for has no effect, because the method is not declared in a type. + /// Custom attributes are not currently supported on dynamic methods. The only attribute returned is ; you can get the method implementation flags more easily using the method. + /// public override object[] GetCustomAttributes(bool inherit) { // support for MethodImplAttribute PCA return [new MethodImplAttribute((MethodImplOptions)GetMethodImplementationFlags())]; } + /// + /// Indicates whether one or more attributes of the specified type or of its derived types is applied to this method. + /// + /// The type of custom attribute to search for. The search includes derived types. + /// This parameter is ignored for dynamic methods, because they do not support inheritance. + /// if one or more instances of or any of its derived types is applied to this method; otherwise, . + /// is . + /// + /// For dynamic methods, specifying for has no effect. Dynamic methods have no inheritance chain. + /// Dynamic methods do not support user-defined custom attributes. This method reports attributes only if is or a base type of it, reflecting the method's implementation flags. + /// public override bool IsDefined(Type attributeType, bool inherit) { ArgumentNullException.ThrowIfNull(attributeType); @@ -372,16 +682,62 @@ public override bool IsDefined(Type attributeType, bool inherit) return attributeType.IsAssignableFrom(typeof(MethodImplAttribute)); } + /// + /// Gets the return type of the dynamic method. + /// + /// A representing the return type of the dynamic method; or if the method has no return type. + /// + /// + /// + /// + /// If was specified for the return type when the dynamic method was created, this property returns . + /// public override Type ReturnType => _returnType; + /// + /// Gets the return parameter of the dynamic method. + /// + /// A object that represents the return parameter of the dynamic method. + /// + /// In modern .NET, this property returns a instance that describes the return value for dynamic methods. In .NET Framework, this property always returns for dynamic methods. + /// public override ParameterInfo ReturnParameter => new RuntimeParameterInfo(this, null, _returnType, -1); + /// + /// Gets the custom attributes of the return type for the dynamic method. + /// + /// An representing the custom attributes of the return type for the dynamic method. + /// + /// + /// + /// + /// Custom attributes are not supported on the return type of a dynamic method, so the array of custom attributes returned by the method is always empty. + /// public override ICustomAttributeProvider ReturnTypeCustomAttributes => new EmptyCAHolder(); // // DynamicMethod specific methods // + /// + /// Defines a parameter of the dynamic method. + /// + /// The position of the parameter in the parameter list. Parameters are indexed beginning with the number 1 for the first parameter. + /// A bitwise combination of values that specifies the attributes of the parameter. + /// The name of the parameter. The name can be a zero-length string. + /// Always returns . + /// The method has no parameters. + /// -or- + /// is less than 0. + /// -or- + /// is greater than the number of parameters of the dynamic method. + /// + /// + /// + /// + /// If is 0, the method refers to the return value. Setting parameter information has no effect on the return value. + /// If the dynamic method has already been completed, by calling the or method, the method has no effect. No exception is thrown. + /// public ParameterBuilder? DefineParameter(int position, ParameterAttributes attributes, string? parameterName) { if (position < 0 || position > _parameterTypes.Length) @@ -397,11 +753,28 @@ public override bool IsDefined(Type attributeType, bool inherit) return null; } + /// + /// Returns a Microsoft intermediate language (MSIL) generator for the method with a default MSIL stream size of 64 bytes. + /// + /// An object for the method. + /// + /// For more information about this API, see Supplemental API remarks for DynamicMethod.GetILGenerator. + /// public ILGenerator GetILGenerator() { return GetILGenerator(64); } + /// + /// Gets or sets a value indicating whether the local variables in the method are zero-initialized. + /// + /// if the local variables in the method are zero-initialized; otherwise, . The default is . + /// + /// + /// + /// + /// If this property is set to , the emitted Microsoft intermediate language (MSIL) includes initialization of local variables. If it is set to , local variables are not initialized and the generated code is unverifiable. + /// public bool InitLocals { get => _initLocals; diff --git a/src/libraries/System.Reflection.Emit.Lightweight/src/System.Reflection.Emit.Lightweight.csproj b/src/libraries/System.Reflection.Emit.Lightweight/src/System.Reflection.Emit.Lightweight.csproj index 74505480ffcede..01b3faeb9af0dd 100644 --- a/src/libraries/System.Reflection.Emit.Lightweight/src/System.Reflection.Emit.Lightweight.csproj +++ b/src/libraries/System.Reflection.Emit.Lightweight/src/System.Reflection.Emit.Lightweight.csproj @@ -3,7 +3,6 @@ $(NetCoreAppCurrent) true - false