From 65515c813a8fb146ee10df7b72b06732450bb073 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 23:45:13 +0000 Subject: [PATCH 1/7] Initial plan From bf5aceebf74cf90898fdb2dc127025f9c605a62b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 23:50:12 +0000 Subject: [PATCH 2/7] Add CustomReflectionContext supplemental API remarks documentation Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- .gitignore | 4 + .../CustomReflectionContextExample.csproj | 12 +++ .../csharp/program.cs | 82 +++++++++++++++++++ ...lection-context-customreflectioncontext.md | 34 ++++++++ docs/fundamentals/toc.yml | 2 + 5 files changed, 134 insertions(+) create mode 100644 docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/CustomReflectionContextExample.csproj create mode 100644 docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs create mode 100644 docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md diff --git a/.gitignore b/.gitignore index aebb12d48e08f..d338b605a42c4 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,7 @@ BenchmarkDotNet.Artifacts # ReplayCheck (temporary) .replaycheck/ + +# Build artifacts +bin/ +obj/ diff --git a/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/CustomReflectionContextExample.csproj b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/CustomReflectionContextExample.csproj new file mode 100644 index 0000000000000..c1471653bed76 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/CustomReflectionContextExample.csproj @@ -0,0 +1,12 @@ + + + + Exe + net10.0 + + + + + + + diff --git a/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs new file mode 100644 index 0000000000000..c23629ec64643 --- /dev/null +++ b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Context; + +namespace ConsoleApplication1 +{ + // + //A blank example attribute. + class myAttribute : Attribute + { + } + + //Reflection context with custom rules. + class myCRC : CustomReflectionContext + { + //Called whenever the reflection context checks for custom attributes. + protected override IEnumerable GetCustomAttributes(MemberInfo member, IEnumerable declaredAttributes) + { + //Add example attribute to "To*" members. + if (member.Name.StartsWith("To")) + { + yield return new myAttribute(); + } + //Keep existing attributes as well. + foreach (var attr in declaredAttributes) yield return attr; + } + } + + class Program + { + static void Main(string[] args) + { + myCRC mc = new myCRC(); + Type t = typeof(String); + + //A representation of the type in the default reflection context. + TypeInfo ti = t.GetTypeInfo(); + + //A representation of the type in the customized reflection context. + TypeInfo myTI = mc.MapType(ti); + + //Display all the members of the type and their attributes. + foreach (MemberInfo m in myTI.DeclaredMembers) + { + Console.WriteLine(m.Name + ":"); + foreach (Attribute cd in m.GetCustomAttributes()) + { + Console.WriteLine(cd.GetType()); + } + } + + Console.WriteLine(); + + //The "ToString" member as represented in the default reflection context. + MemberInfo mi1 = ti.GetDeclaredMethods("ToString").FirstOrDefault(); + + //All the attributes of "ToString" in the default reflection context. + Console.WriteLine("'ToString' Attributes in Default Reflection Context:"); + foreach (Attribute cd in mi1.GetCustomAttributes()) + { + Console.WriteLine(cd.GetType()); + } + + Console.WriteLine(); + + //The same member in the custom reflection context. + mi1 = myTI.GetDeclaredMethods("ToString").FirstOrDefault(); + + //All its attributes, for comparison. myAttribute is now included. + Console.WriteLine("'ToString' Attributes in Custom Reflection Context:"); + foreach (Attribute cd in mi1.GetCustomAttributes()) + { + Console.WriteLine(cd.GetType()); + } + + Console.ReadLine(); + } + } + // +} diff --git a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md new file mode 100644 index 0000000000000..6f55e25e2a44b --- /dev/null +++ b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md @@ -0,0 +1,34 @@ +--- +title: System.Reflection.Context.CustomReflectionContext class +description: Learn about the System.Reflection.Context.CustomReflectionContext class. +ms.date: 02/12/2026 +ai-usage: ai-assisted +--- +# System.Reflection.Context.CustomReflectionContext class + +[!INCLUDE [context](includes/context.md)] + + provides a way for you to add or remove custom attributes from reflection objects, or add dummy properties to those objects, without re-implementing the complete reflection model. The default simply wraps reflection objects without making any changes, but by subclassing and overriding the relevant methods, you can add, remove, or change the attributes that apply to any reflected parameter or member, or add new properties to a reflected type. + +For example, suppose that your code follows the convention of applying a particular attribute to factory methods, but you're now required to work with third-party code that lacks attributes. You can use to specify a rule for identifying the objects that should have attributes and to supply the objects with those attributes when they're viewed from your code. + +To use effectively, the code that uses the reflected objects must support the notion of specifying a reflection context, instead of assuming that all reflected objects are associated with the runtime reflection context. Many reflection methods in the .NET Framework provide a parameter for this purpose. + +To modify the attributes that are applied to a reflected parameter or member, override the or method. These methods take the reflected object and the list of attributes under its current reflection context, and return the list of attributes it should have under the custom reflection context. + +> [!WARNING] +> methods should not access the list of attributes of a reflected object or method directly by calling the method on the provided or instance, but should instead use the `declaredAttributes` list, which is passed as a parameter to the method overloads. + +To add properties to a reflected type, override the method. The method accepts a parameter that specifies the reflected type, and returns a list of additional properties. You should use the method to create property objects to return. You can specify delegates when creating the property that serve as the property accessor, and you can omit one of the accessors to create a read-only or write-only property. Note that such dummy properties have no metadata or Common Intermediate Language (CIL) backing. + +> [!WARNING] +> Be cautious about equality among reflected objects when you work with reflection contexts, because objects might represent the same reflected object in multiple contexts. You can use the method to obtain a particular reflection context's version of a reflected object. + +> [!WARNING] +> A object alters the attributes returned by a particular reflection object, such as those obtained by the method. It doesn't alter the custom attribute data returned by the method, and these two lists won't match when you use a custom reflection context. + +## Example + +The following example demonstrates how to subclass to add a custom attribute to all the members of a given type whose names begin with "To". To run this code, paste it into an empty console project, and make sure to include a reference to System.Reflection.Context.dll. + +:::code language="csharp" source="./snippets/system-reflection-context-customreflectioncontext/csharp/program.cs" id="Snippet1"::: diff --git a/docs/fundamentals/toc.yml b/docs/fundamentals/toc.yml index b59d223cc2de6..c6b1727205d44 100644 --- a/docs/fundamentals/toc.yml +++ b/docs/fundamentals/toc.yml @@ -1394,6 +1394,8 @@ items: href: runtime-libraries/system-type-gettype.md - name: MakeGenericType method href: runtime-libraries/system-type-makegenerictype.md + - name: The CustomReflectionContext class + href: runtime-libraries/system-reflection-context-customreflectioncontext.md - name: Graphics items: - name: Supplemental API remarks From b55cafd013b350f77bfaf3db9f6483ca31c3f084 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:54:24 -0800 Subject: [PATCH 3/7] Update docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../system-reflection-context-customreflectioncontext.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md index 6f55e25e2a44b..e40a4aaec1729 100644 --- a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md +++ b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md @@ -29,6 +29,6 @@ To add properties to a reflected type, override the to add a custom attribute to all the members of a given type whose names begin with "To". To run this code, paste it into an empty console project, and make sure to include a reference to System.Reflection.Context.dll. +The following example demonstrates how to subclass to add a custom attribute to all the members of a given type whose names begin with "To". To run this code, paste it into an empty console project and add a reference to the `System.Reflection.Context` NuGet package. :::code language="csharp" source="./snippets/system-reflection-context-customreflectioncontext/csharp/program.cs" id="Snippet1"::: From 237bab67cdf5a08df2c4aca4ba359313f4187af0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 00:56:56 +0000 Subject: [PATCH 4/7] Update class names to follow PascalCase naming conventions Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- .../csharp/program.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs index c23629ec64643..4527a78c7d647 100644 --- a/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs +++ b/docs/fundamentals/runtime-libraries/snippets/system-reflection-context-customreflectioncontext/csharp/program.cs @@ -8,12 +8,12 @@ namespace ConsoleApplication1 { // //A blank example attribute. - class myAttribute : Attribute + class MyAttribute : Attribute { } //Reflection context with custom rules. - class myCRC : CustomReflectionContext + class MyCustomReflectionContext : CustomReflectionContext { //Called whenever the reflection context checks for custom attributes. protected override IEnumerable GetCustomAttributes(MemberInfo member, IEnumerable declaredAttributes) @@ -21,7 +21,7 @@ protected override IEnumerable GetCustomAttributes(MemberInfo member, IE //Add example attribute to "To*" members. if (member.Name.StartsWith("To")) { - yield return new myAttribute(); + yield return new MyAttribute(); } //Keep existing attributes as well. foreach (var attr in declaredAttributes) yield return attr; @@ -32,7 +32,7 @@ class Program { static void Main(string[] args) { - myCRC mc = new myCRC(); + MyCustomReflectionContext mc = new MyCustomReflectionContext(); Type t = typeof(String); //A representation of the type in the default reflection context. @@ -68,7 +68,7 @@ static void Main(string[] args) //The same member in the custom reflection context. mi1 = myTI.GetDeclaredMethods("ToString").FirstOrDefault(); - //All its attributes, for comparison. myAttribute is now included. + //All its attributes, for comparison. MyAttribute is now included. Console.WriteLine("'ToString' Attributes in Custom Reflection Context:"); foreach (Attribute cd in mi1.GetCustomAttributes()) { From 08c3dabb987f2e180efffa4297ff384fdb08812d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 01:03:34 +0000 Subject: [PATCH 5/7] Revert .gitignore changes per feedback Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com> --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index d338b605a42c4..aebb12d48e08f 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,3 @@ BenchmarkDotNet.Artifacts # ReplayCheck (temporary) .replaycheck/ - -# Build artifacts -bin/ -obj/ From 268c1460aff63fd2b70e75f3347056599dc36300 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:09:51 -0800 Subject: [PATCH 6/7] Clean up duplicate warning Removed duplicate warning about equality among reflected objects and custom attributes. --- .../system-reflection-context-customreflectioncontext.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md index e40a4aaec1729..fafb336855ef8 100644 --- a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md +++ b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md @@ -22,10 +22,8 @@ To modify the attributes that are applied to a reflected parameter or member, ov To add properties to a reflected type, override the method. The method accepts a parameter that specifies the reflected type, and returns a list of additional properties. You should use the method to create property objects to return. You can specify delegates when creating the property that serve as the property accessor, and you can omit one of the accessors to create a read-only or write-only property. Note that such dummy properties have no metadata or Common Intermediate Language (CIL) backing. > [!WARNING] -> Be cautious about equality among reflected objects when you work with reflection contexts, because objects might represent the same reflected object in multiple contexts. You can use the method to obtain a particular reflection context's version of a reflected object. - -> [!WARNING] -> A object alters the attributes returned by a particular reflection object, such as those obtained by the method. It doesn't alter the custom attribute data returned by the method, and these two lists won't match when you use a custom reflection context. +> - Be cautious about equality among reflected objects when you work with reflection contexts, because objects might represent the same reflected object in multiple contexts. You can use the method to obtain a particular reflection context's version of a reflected object. +> - A object alters the attributes returned by a particular reflection object, such as those obtained by the method. It doesn't alter the custom attribute data returned by the method, and these two lists won't match when you use a custom reflection context. ## Example From 35304ae9af2811c94045c36101821a6d436eec2b Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:13:03 -0800 Subject: [PATCH 7/7] Update docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md --- .../system-reflection-context-customreflectioncontext.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md index fafb336855ef8..4a0c4689f0480 100644 --- a/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md +++ b/docs/fundamentals/runtime-libraries/system-reflection-context-customreflectioncontext.md @@ -22,6 +22,7 @@ To modify the attributes that are applied to a reflected parameter or member, ov To add properties to a reflected type, override the method. The method accepts a parameter that specifies the reflected type, and returns a list of additional properties. You should use the method to create property objects to return. You can specify delegates when creating the property that serve as the property accessor, and you can omit one of the accessors to create a read-only or write-only property. Note that such dummy properties have no metadata or Common Intermediate Language (CIL) backing. > [!WARNING] +> > - Be cautious about equality among reflected objects when you work with reflection contexts, because objects might represent the same reflected object in multiple contexts. You can use the method to obtain a particular reflection context's version of a reflected object. > - A object alters the attributes returned by a particular reflection object, such as those obtained by the method. It doesn't alter the custom attribute data returned by the method, and these two lists won't match when you use a custom reflection context.