Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,30 @@ public sealed partial class DynamicMethod : MethodInfo
// Delegate and method creation
//

/// <summary>
/// Completes the dynamic method and creates a delegate that can be used to execute it.
/// </summary>
/// <param name="delegateType">A delegate type whose signature matches that of the dynamic method.</param>
/// <returns>A delegate of the specified type, which can be used to execute the dynamic method.</returns>
/// <exception cref="InvalidOperationException">The dynamic method has no method body.</exception>
/// <exception cref="ArgumentException"><paramref name="delegateType" /> has the wrong number of parameters or the wrong parameter types.</exception>
/// <remarks>
/// For more information about this API, see <see href="https://raw.githubusercontent.com/dotnet/docs/main/docs/fundamentals/runtime-libraries/system-reflection-emit-dynamicmethod-createdelegate.md">Supplemental API remarks for DynamicMethod.CreateDelegate</see>.
/// </remarks>
public sealed override Delegate CreateDelegate(Type delegateType) =>
CreateDelegate(delegateType, target: null);

/// <summary>
/// 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.
/// </summary>
/// <param name="delegateType">A delegate type whose signature matches that of the dynamic method, minus the first parameter.</param>
/// <param name="target">An object the delegate is bound to. Must be of the same type as the first parameter of the dynamic method.</param>
/// <returns>A delegate of the specified type, which can be used to execute the dynamic method with the specified target object.</returns>
/// <exception cref="InvalidOperationException">The dynamic method has no method body.</exception>
/// <exception cref="ArgumentException"><paramref name="delegateType" /> has the wrong number of parameters or the wrong parameter types.</exception>
/// <remarks>
/// For more information about this API, see <see href="https://raw.githubusercontent.com/dotnet/docs/main/docs/fundamentals/runtime-libraries/system-reflection-emit-dynamicmethod-createdelegate.md">Supplemental API remarks for DynamicMethod.CreateDelegate</see>.
/// </remarks>
public sealed override Delegate CreateDelegate(Type delegateType, object? target)
{
if (_restrictedSkipVisibility)
Expand Down Expand Up @@ -114,6 +135,21 @@ Signature LazyCreateSignature()
}
}

/// <summary>
/// Invokes the dynamic method using the specified parameters, under the constraints of the specified binder, with the specified culture information.
/// </summary>
/// <param name="obj">This parameter is ignored for dynamic methods, because they are static. Specify <see langword="null" />.</param>
/// <param name="invokeAttr">A bitwise combination of <see cref="BindingFlags" /> values.</param>
/// <param name="binder">A <see cref="Binder" /> object that enables the binding, coercion of argument types, invocation of members, and retrieval of <see cref="System.Reflection.MemberInfo" /> objects through reflection. If <paramref name="binder" /> is <see langword="null" />, the default binder is used.</param>
/// <param name="parameters">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 <see langword="null" />.</param>
/// <param name="culture">An instance of <see cref="CultureInfo" /> used to govern the coercion of types. If this is <see langword="null" />, the <see cref="CultureInfo" /> for the current thread is used.</param>
/// <returns>An <see cref="object" /> containing the return value of the invoked method.</returns>
/// <exception cref="TargetParameterCountException">The number of elements in <paramref name="parameters" /> does not match the number of parameters in the dynamic method.</exception>
/// <exception cref="NotSupportedException">The dynamic method contains unverifiable code.</exception>
/// <exception cref="InvalidOperationException">The dynamic method has no method body.</exception>
/// <remarks>
/// For more information about this API, see <see href="https://raw.githubusercontent.com/dotnet/docs/main/docs/fundamentals/runtime-libraries/system-reflection-emit-dynamicmethod-invoke.md">Supplemental API remarks for DynamicMethod.Invoke</see>.
/// </remarks>
public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
{
if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
Expand Down Expand Up @@ -143,6 +179,13 @@ Signature LazyCreateSignature()
return retValue;
}

/// <summary>
/// Returns a <see cref="DynamicILInfo" /> object that can be used to generate a method body from metadata tokens, scopes, and Microsoft intermediate language (MSIL) streams.
/// </summary>
/// <returns>A <see cref="DynamicILInfo" /> object that can be used to generate a method body from metadata tokens, scopes, and MSIL streams.</returns>
/// <remarks>
/// The <see cref="DynamicILInfo" /> class is provided to support unmanaged code generation.
/// </remarks>
public DynamicILInfo GetDynamicILInfo()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Why didn't you backport the <remarks> here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added GetDynamicILInfo remarks in commit 2f4fe14.

{
if (_dynamicILInfo == null)
Expand All @@ -154,6 +197,14 @@ public DynamicILInfo GetDynamicILInfo()
return _dynamicILInfo;
}

/// <summary>
/// Returns a Microsoft intermediate language (MSIL) generator for the method with the specified MSIL stream size.
/// </summary>
/// <param name="streamSize">The size of the MSIL stream, in bytes.</param>
/// <returns>An <see cref="ILGenerator" /> object for the method.</returns>
/// <remarks>
/// For more information about this API, see <see href="https://raw.githubusercontent.com/dotnet/docs/main/docs/fundamentals/runtime-libraries/system-reflection-emit-dynamicmethod-getilgenerator.md">Supplemental API remarks for DynamicMethod.GetILGenerator</see>.
/// </remarks>
public ILGenerator GetILGenerator(int streamSize)
{
if (_ilGenerator == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -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 ICustomeAttributeProvider
// 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!;
}
}
Loading
Loading