Skip to content

Commit bae73d6

Browse files
richlanderCopilot
andcommitted
Switch DynamicMethod samples from regions to methods
Restructure DynamicMethod.Examples.cs to use self-contained static methods instead of #region/#endregion directives. Each method creates its own DynamicMethod and is independently runnable — addressing feedback that samples should be copy-paste compilable. Three methods replace the many small regions: - MetadataAndProperties: Name, DeclaringType, Module, Attributes, etc. - DefineParameterAndGetParameters: parameter metadata - GetILGeneratorAndInvoke: IL emission, delegates, and Invoke Update <code> tags in DynamicMethod.cs and samples.json to use method= instead of region= for Examples.cs entries. Overview.cs and CtorOwnerType.cs retain their existing region-based approach (single self-contained regions). Addresses feedback from jkotas on PR #124407. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8a8f318 commit bae73d6

3 files changed

Lines changed: 122 additions & 152 deletions

File tree

Lines changed: 93 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,106 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// Runnable examples for DynamicMethod XML doc comments.
4-
// Each #region is referenced by <code> tags in DynamicMethod.cs.
4+
// Each static method is a self-contained sample referenced by <code> tags in DynamicMethod.cs.
55
// Run: dotnet run DynamicMethod.Examples.cs
66

77
using System.Globalization;
88
using System.Reflection;
99
using System.Reflection.Emit;
1010

11-
// Create a DynamicMethod shared by the property/method examples below.
12-
DynamicMethod hello = new("Hello", typeof(int), [typeof(string), typeof(int)], typeof(string).Module);
13-
int failures = 0;
11+
DynamicMethodExamples.MetadataAndProperties();
12+
DynamicMethodExamples.DefineParameterAndGetParameters();
13+
DynamicMethodExamples.GetILGeneratorAndInvoke();
1414

15-
void Fail(string name, string message)
16-
{
17-
Console.Error.WriteLine($"FAIL: {name}{message}");
18-
failures++;
19-
}
15+
Console.WriteLine("All examples passed.");
16+
return 0;
2017

21-
#region Name
22-
// The name specified when the dynamic method was created.
23-
Console.WriteLine($"Name: {hello.Name}");
24-
#endregion
25-
if (hello.Name != "Hello") Fail("Name", $"Expected 'Hello', got '{hello.Name}'");
26-
27-
#region DeclaringType
28-
// DeclaringType is always null for dynamic methods.
29-
Console.WriteLine($"DeclaringType: {hello.DeclaringType?.ToString() ?? "(null)"}");
30-
#endregion
31-
if (hello.DeclaringType is not null) Fail("DeclaringType", "Expected null");
32-
33-
#region ReflectedType
34-
// ReflectedType is always null for dynamic methods.
35-
Console.WriteLine($"ReflectedType: {hello.ReflectedType?.ToString() ?? "(null)"}");
36-
#endregion
37-
if (hello.ReflectedType is not null) Fail("ReflectedType", "Expected null");
38-
39-
#region Module
40-
// The module the dynamic method is associated with.
41-
Console.WriteLine($"Module: {hello.Module}");
42-
#endregion
43-
if (hello.Module != typeof(string).Module) Fail("Module", "Expected System.Private.CoreLib module");
44-
45-
#region Attributes
46-
// Dynamic methods always have Public | Static attributes.
47-
Console.WriteLine($"Attributes: {hello.Attributes}");
48-
#endregion
49-
if (hello.Attributes != (MethodAttributes.Public | MethodAttributes.Static))
50-
Fail("Attributes", $"Expected Public | Static, got {hello.Attributes}");
51-
52-
#region CallingConvention
53-
// Dynamic methods always use Standard calling convention.
54-
Console.WriteLine($"CallingConvention: {hello.CallingConvention}");
55-
#endregion
56-
if (hello.CallingConvention != CallingConventions.Standard)
57-
Fail("CallingConvention", $"Expected Standard, got {hello.CallingConvention}");
58-
59-
#region InitLocals
60-
// InitLocals defaults to true — local variables are zero-initialized.
61-
Console.WriteLine($"InitLocals: {hello.InitLocals}");
62-
#endregion
63-
if (!hello.InitLocals) Fail("InitLocals", "Expected true");
64-
65-
#region ReturnType
66-
// The return type specified when the dynamic method was created.
67-
Console.WriteLine($"ReturnType: {hello.ReturnType}");
68-
#endregion
69-
if (hello.ReturnType != typeof(int)) Fail("ReturnType", $"Expected Int32, got {hello.ReturnType}");
70-
71-
#region ReturnTypeCustomAttributes
72-
// At present there is no way to set custom attributes on the return type,
73-
// so the list is always empty.
74-
ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;
75-
object[] returnAttributes = caProvider.GetCustomAttributes(true);
76-
Console.WriteLine($"Return type custom attributes: {returnAttributes.Length}");
77-
#endregion
78-
if (returnAttributes.Length != 0) Fail("ReturnTypeCustomAttributes", "Expected 0 attributes");
79-
80-
#region DefineParameter
81-
// Optionally add parameter metadata (useful for debugging).
82-
hello.DefineParameter(1, ParameterAttributes.In, "message");
83-
hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn");
84-
#endregion
85-
86-
#region GetParameters
87-
// Retrieve parameter info after calling DefineParameter.
88-
ParameterInfo[] parameters = hello.GetParameters();
89-
foreach (ParameterInfo p in parameters)
90-
Console.WriteLine($" Param: {p.Name}, {p.ParameterType}, {p.Attributes}");
91-
#endregion
92-
if (parameters.Length != 2) Fail("GetParameters", $"Expected 2 parameters, got {parameters.Length}");
93-
94-
#region ToString
95-
// ToString returns the signature: return type, name, and parameter types.
96-
string sig = hello.ToString();
97-
Console.WriteLine($"ToString: {sig}");
98-
#endregion
99-
if (!sig.Contains("Hello")) Fail("ToString", $"Expected signature to contain 'Hello'");
100-
101-
// Emit a method body so we can test CreateDelegate and Invoke.
102-
MethodInfo writeString = typeof(Console).GetMethod("WriteLine", [typeof(string)])!;
103-
104-
#region GetILGenerator
105-
// Get an ILGenerator to emit the method body.
106-
ILGenerator il = hello.GetILGenerator();
107-
il.Emit(OpCodes.Ldarg_0);
108-
il.EmitCall(OpCodes.Call, writeString, null);
109-
il.Emit(OpCodes.Ldarg_1);
110-
il.Emit(OpCodes.Ret);
111-
#endregion
112-
113-
#region CreateDelegate
114-
// Create a strongly-typed delegate for the dynamic method.
115-
Func<string, int, int> hi = hello.CreateDelegate<Func<string, int, int>>();
116-
int retval = hi("Hello from delegate!", 42);
117-
Console.WriteLine($"Delegate returned: {retval}");
118-
#endregion
119-
if (retval != 42) Fail("CreateDelegate", $"Expected 42, got {retval}");
120-
121-
#region Invoke
122-
// Invoke the dynamic method via reflection (slower than a delegate).
123-
object? objRet = hello.Invoke(null, BindingFlags.ExactBinding, null,
124-
["Hello from Invoke!", 99], CultureInfo.InvariantCulture);
125-
Console.WriteLine($"Invoke returned: {objRet}");
126-
#endregion
127-
if (objRet is not 99) Fail("Invoke", $"Expected 99, got {objRet}");
128-
129-
if (failures > 0)
18+
class DynamicMethodExamples
13019
{
131-
Console.Error.WriteLine($"\n{failures} example(s) failed.");
132-
return 1;
20+
/// <summary>
21+
/// Shows the metadata properties of a DynamicMethod: Name, DeclaringType, ReflectedType,
22+
/// Module, Attributes, CallingConvention, ReturnType, ReturnTypeCustomAttributes, InitLocals,
23+
/// and ToString.
24+
/// </summary>
25+
public static void MetadataAndProperties()
26+
{
27+
// Create a dynamic method associated with a module.
28+
DynamicMethod hello = new("Hello", typeof(int), [typeof(string), typeof(int)], typeof(string).Module);
29+
30+
// Name: the name specified at creation.
31+
Console.WriteLine($"Name: {hello.Name}");
32+
33+
// DeclaringType is always null for dynamic methods.
34+
Console.WriteLine($"DeclaringType: {hello.DeclaringType?.ToString() ?? "(null)"}");
35+
36+
// ReflectedType is always null for dynamic methods.
37+
Console.WriteLine($"ReflectedType: {hello.ReflectedType?.ToString() ?? "(null)"}");
38+
39+
// Module: the module the dynamic method is associated with.
40+
Console.WriteLine($"Module: {hello.Module}");
41+
42+
// Attributes are always Public | Static.
43+
Console.WriteLine($"Attributes: {hello.Attributes}");
44+
45+
// CallingConvention is always Standard.
46+
Console.WriteLine($"CallingConvention: {hello.CallingConvention}");
47+
48+
// ReturnType: the return type specified at creation.
49+
Console.WriteLine($"ReturnType: {hello.ReturnType}");
50+
51+
// ReturnTypeCustomAttributes: no way to set custom attributes on the return type.
52+
ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;
53+
object[] returnAttributes = caProvider.GetCustomAttributes(true);
54+
Console.WriteLine($"Return type custom attributes: {returnAttributes.Length}");
55+
56+
// InitLocals defaults to true — local variables are zero-initialized.
57+
Console.WriteLine($"InitLocals: {hello.InitLocals}");
58+
59+
// ToString returns the method signature (return type, name, parameter types).
60+
Console.WriteLine($"ToString: {hello.ToString()}");
61+
}
62+
63+
/// <summary>
64+
/// Shows DefineParameter and GetParameters: adding parameter metadata and retrieving it.
65+
/// </summary>
66+
public static void DefineParameterAndGetParameters()
67+
{
68+
DynamicMethod hello = new("Hello", typeof(int), [typeof(string), typeof(int)], typeof(string).Module);
69+
70+
// DefineParameter adds metadata such as name and attributes.
71+
// Parameter positions are 1-based; position 0 refers to the return value.
72+
hello.DefineParameter(1, ParameterAttributes.In, "message");
73+
hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn");
74+
75+
// GetParameters retrieves the parameter info.
76+
ParameterInfo[] parameters = hello.GetParameters();
77+
foreach (ParameterInfo p in parameters)
78+
Console.WriteLine($" Param: {p.Name}, {p.ParameterType}, {p.Attributes}");
79+
}
80+
81+
/// <summary>
82+
/// Shows GetILGenerator, CreateDelegate, and Invoke: emitting a method body and calling it.
83+
/// </summary>
84+
public static void GetILGeneratorAndInvoke()
85+
{
86+
DynamicMethod hello = new("Hello", typeof(int), [typeof(string), typeof(int)], typeof(string).Module);
87+
MethodInfo writeString = typeof(Console).GetMethod("WriteLine", [typeof(string)])!;
88+
89+
// GetILGenerator returns an ILGenerator for emitting the method body.
90+
ILGenerator il = hello.GetILGenerator();
91+
il.Emit(OpCodes.Ldarg_0); // push first arg (string)
92+
il.EmitCall(OpCodes.Call, writeString, null); // Console.WriteLine(string)
93+
il.Emit(OpCodes.Ldarg_1); // push second arg (int)
94+
il.Emit(OpCodes.Ret); // return it
95+
96+
// CreateDelegate produces a strongly-typed delegate for the dynamic method.
97+
Func<string, int, int> hi = hello.CreateDelegate<Func<string, int, int>>();
98+
int retval = hi("Hello from delegate!", 42);
99+
Console.WriteLine($"Delegate returned: {retval}");
100+
101+
// Invoke calls the dynamic method via reflection (slower than a delegate).
102+
object? objRet = hello.Invoke(null, BindingFlags.ExactBinding, null,
103+
["Hello from Invoke!", 99], CultureInfo.InvariantCulture);
104+
Console.WriteLine($"Invoke returned: {objRet}");
105+
}
133106
}
134-
135-
Console.WriteLine("\nAll examples passed.");
136-
return 0;

src/libraries/System.Private.CoreLib/samples/samples.json

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22
"T:System.Reflection.Emit.DynamicMethod": { "file": "System/Reflection/Emit/DynamicMethod.Overview.cs", "region": "CreateAndInvoke", "title": "Creating and invoking a DynamicMethod" },
33
"M:System.Reflection.Emit.DynamicMethod.#ctor(System.String,System.Type,System.Type[],System.Reflection.Module)": { "file": "System/Reflection/Emit/DynamicMethod.Overview.cs", "region": "CreateAndInvoke", "title": "Creating a DynamicMethod associated with a module" },
44
"M:System.Reflection.Emit.DynamicMethod.#ctor(System.String,System.Type,System.Type[],System.Type)": { "file": "System/Reflection/Emit/DynamicMethod.CtorOwnerType.cs", "region": "OwnerTypeAccess", "title": "Creating a DynamicMethod with an owner type" },
5-
"P:System.Reflection.Emit.DynamicMethod.Name": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "Name", "title": "Getting the name of a DynamicMethod" },
6-
"P:System.Reflection.Emit.DynamicMethod.DeclaringType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "DeclaringType", "title": "Getting the declaring type of a DynamicMethod" },
7-
"P:System.Reflection.Emit.DynamicMethod.ReflectedType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "ReflectedType", "title": "Getting the reflected type of a DynamicMethod" },
8-
"P:System.Reflection.Emit.DynamicMethod.Module": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "Module", "title": "Getting the module of a DynamicMethod" },
9-
"P:System.Reflection.Emit.DynamicMethod.Attributes": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "Attributes", "title": "Getting the attributes of a DynamicMethod" },
10-
"P:System.Reflection.Emit.DynamicMethod.CallingConvention": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "CallingConvention", "title": "Getting the calling convention of a DynamicMethod" },
11-
"P:System.Reflection.Emit.DynamicMethod.ReturnType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "ReturnType", "title": "Getting the return type of a DynamicMethod" },
12-
"P:System.Reflection.Emit.DynamicMethod.ReturnTypeCustomAttributes": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "ReturnTypeCustomAttributes", "title": "Getting return type custom attributes" },
13-
"P:System.Reflection.Emit.DynamicMethod.InitLocals": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "InitLocals", "title": "Checking InitLocals on a DynamicMethod" },
14-
"M:System.Reflection.Emit.DynamicMethod.ToString": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "ToString", "title": "Getting the string representation of a DynamicMethod" },
15-
"M:System.Reflection.Emit.DynamicMethod.GetParameters": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "GetParameters", "title": "Getting parameter info from a DynamicMethod" },
16-
"M:System.Reflection.Emit.DynamicMethod.DefineParameter(System.Int32,System.Reflection.ParameterAttributes,System.String)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "DefineParameter", "title": "Defining parameters on a DynamicMethod" },
17-
"M:System.Reflection.Emit.DynamicMethod.GetILGenerator": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "GetILGenerator", "title": "Getting the IL generator for a DynamicMethod" },
18-
"M:System.Reflection.Emit.DynamicMethod.GetILGenerator(System.Int32)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "GetILGenerator", "title": "Getting the IL generator for a DynamicMethod" },
19-
"M:System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "CreateDelegate", "title": "Creating a delegate from a DynamicMethod" },
5+
"P:System.Reflection.Emit.DynamicMethod.Name": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
6+
"P:System.Reflection.Emit.DynamicMethod.DeclaringType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
7+
"P:System.Reflection.Emit.DynamicMethod.ReflectedType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
8+
"P:System.Reflection.Emit.DynamicMethod.Module": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
9+
"P:System.Reflection.Emit.DynamicMethod.Attributes": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
10+
"P:System.Reflection.Emit.DynamicMethod.CallingConvention": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
11+
"P:System.Reflection.Emit.DynamicMethod.ReturnType": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
12+
"P:System.Reflection.Emit.DynamicMethod.ReturnTypeCustomAttributes": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
13+
"P:System.Reflection.Emit.DynamicMethod.InitLocals": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
14+
"M:System.Reflection.Emit.DynamicMethod.ToString": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "MetadataAndProperties", "title": "DynamicMethod metadata properties" },
15+
"M:System.Reflection.Emit.DynamicMethod.GetParameters": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "DefineParameterAndGetParameters", "title": "Defining and retrieving DynamicMethod parameters" },
16+
"M:System.Reflection.Emit.DynamicMethod.DefineParameter(System.Int32,System.Reflection.ParameterAttributes,System.String)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "DefineParameterAndGetParameters", "title": "Defining and retrieving DynamicMethod parameters" },
17+
"M:System.Reflection.Emit.DynamicMethod.GetILGenerator": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "GetILGeneratorAndInvoke", "title": "Emitting IL and invoking a DynamicMethod" },
18+
"M:System.Reflection.Emit.DynamicMethod.GetILGenerator(System.Int32)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "GetILGeneratorAndInvoke", "title": "Emitting IL and invoking a DynamicMethod" },
19+
"M:System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "GetILGeneratorAndInvoke", "title": "Emitting IL and invoking a DynamicMethod" },
2020
"M:System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type,System.Object)": { "file": "System/Reflection/Emit/DynamicMethod.CtorOwnerType.cs", "region": "OwnerTypeAccess", "title": "Creating a bound delegate from a DynamicMethod" },
21-
"M:System.Reflection.Emit.DynamicMethod.Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "region": "Invoke", "title": "Invoking a DynamicMethod via reflection" }
21+
"M:System.Reflection.Emit.DynamicMethod.Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)": { "file": "System/Reflection/Emit/DynamicMethod.Examples.cs", "method": "GetILGeneratorAndInvoke", "title": "Emitting IL and invoking a DynamicMethod" }
2222
}

0 commit comments

Comments
 (0)