From d338d340e8775a6e08fd562985ece7ebcba71c08 Mon Sep 17 00:00:00 2001 From: SmallSoft Date: Wed, 2 Aug 2023 22:28:38 +0500 Subject: [PATCH 1/3] Add documentation for CustomAttrbute --- .../Overview/CustomAttributeSnippets.cs | 63 +++++++++++++++++++ .../Overview/CustomAttributeSnippets.csproj | 9 +++ .../CustomAttribute/Overview/Program.cs | 9 +++ .../CustomAttribute.xml | 16 ++++- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs create mode 100644 snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.csproj create mode 100644 snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/Program.cs diff --git a/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs new file mode 100644 index 00000000000..3c853d904e9 --- /dev/null +++ b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + +static class CustomAttributeSnippets +{ + // + static void PrintCustomAttributes(MetadataReader mr, TypeDefinition t) + { + // Enumerate custom attributes on the type definition + foreach (CustomAttributeHandle attrHandle in t.GetCustomAttributes()) + { + CustomAttribute attr = mr.GetCustomAttribute(attrHandle); + + // Display the attribute type full name + if (attr.Constructor.Kind == HandleKind.MethodDefinition) + { + MethodDefinition mdef = mr.GetMethodDefinition((MethodDefinitionHandle)attr.Constructor); + TypeDefinition tdef = mr.GetTypeDefinition(mdef.GetDeclaringType()); + Console.WriteLine($"Type: {mr.GetString(tdef.Namespace)}.{mr.GetString(tdef.Name)}"); + } + else if (attr.Constructor.Kind == HandleKind.MemberReference) + { + MemberReference mref = mr.GetMemberReference((MemberReferenceHandle)attr.Constructor); + + if (mref.Parent.Kind == HandleKind.TypeReference) + { + TypeReference tref = mr.GetTypeReference((TypeReferenceHandle)mref.Parent); + Console.WriteLine($"Type: {mr.GetString(tref.Namespace)}.{mr.GetString(tref.Name)}"); + } + else if (mref.Parent.Kind == HandleKind.TypeDefinition) + { + TypeDefinition tdef = mr.GetTypeDefinition((TypeDefinitionHandle)mref.Parent); + Console.WriteLine($"Type: {mr.GetString(tdef.Namespace)}.{mr.GetString(tdef.Name)}"); + } + } + + // Display the attribute value + byte[] data = mr.GetBlobBytes(attr.Value); + Console.Write("Value: "); + + for (int i = 0; i < data.Length; i++) Console.Write($"{data[i]:X2} "); + + Console.WriteLine(); + } + } + // + + public static void Run() + { + using var fs = new FileStream(typeof(Program).Assembly.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var peReader = new PEReader(fs); + MetadataReader mr = peReader.GetMetadataReader(); + + foreach(TypeDefinitionHandle tdh in mr.TypeDefinitions) + { + TypeDefinition t = mr.GetTypeDefinition(tdh); + Console.WriteLine($"{mr.GetString(t.Namespace)}.{mr.GetString(t.Name)}"); + PrintCustomAttributes(mr, t); + } + } +} diff --git a/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.csproj b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.csproj new file mode 100644 index 00000000000..8c8d40ddc3a --- /dev/null +++ b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.csproj @@ -0,0 +1,9 @@ + + + + Exe + net7.0 + enable + + + diff --git a/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/Program.cs b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/Program.cs new file mode 100644 index 00000000000..9a620a66702 --- /dev/null +++ b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/Program.cs @@ -0,0 +1,9 @@ +using System; + +class Program +{ + static void Main() + { + CustomAttributeSnippets.Run(); + } +} diff --git a/xml/System.Reflection.Metadata/CustomAttribute.xml b/xml/System.Reflection.Metadata/CustomAttribute.xml index 02b20b39f6d..ca2c36edd2c 100644 --- a/xml/System.Reflection.Metadata/CustomAttribute.xml +++ b/xml/System.Reflection.Metadata/CustomAttribute.xml @@ -31,8 +31,20 @@ - To be added. - To be added. + Provides information about the custom attribute. + + method to get a custom attribute instance. For more information about attributes in .NET, see [Extend metadata using attributes](/dotnet/standard/attributes/). + +## Examples +This example shows how to print all custom attributes applied to the type definition: + +:::code language="csharp" source="~/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs" id="SnippetPrintAttributes"::: + + ]]> + From 7bdcaca89fdee54bd4175ec82835c89a0c61e08e Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Tue, 15 Aug 2023 14:17:00 -0700 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- xml/System.Reflection.Metadata/CustomAttribute.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/System.Reflection.Metadata/CustomAttribute.xml b/xml/System.Reflection.Metadata/CustomAttribute.xml index ca2c36edd2c..0ad681866d2 100644 --- a/xml/System.Reflection.Metadata/CustomAttribute.xml +++ b/xml/System.Reflection.Metadata/CustomAttribute.xml @@ -31,12 +31,12 @@ - Provides information about the custom attribute. + Provides information about a custom attribute. method to get a custom attribute instance. For more information about attributes in .NET, see [Extend metadata using attributes](/dotnet/standard/attributes/). +A custom attribute is an annotation that associates additional information with a metadata element, such as an assembly, type, or method. You can use the method to get a custom attribute instance. For more information about attributes in .NET, see [Extend metadata using attributes](/dotnet/standard/attributes/). ## Examples This example shows how to print all custom attributes applied to the type definition: From feb6a879d36ebd0e9b95965d445200a20c1460e5 Mon Sep 17 00:00:00 2001 From: SmallSoft Date: Thu, 17 Aug 2023 21:09:17 +0500 Subject: [PATCH 3/3] Add user-defined attributes --- .../Overview/CustomAttributeSnippets.cs | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs index 3c853d904e9..63d4bf7bdfa 100644 --- a/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs +++ b/snippets/csharp/System.Reflection.Metadata/CustomAttribute/Overview/CustomAttributeSnippets.cs @@ -6,6 +6,17 @@ static class CustomAttributeSnippets { // + class MyAttribute : Attribute + { + public int X { get; set; } + } + + [My(X = 1)] + class ExampleType1 { } + + [My(X = 2)] + class ExampleType2 { } + static void PrintCustomAttributes(MetadataReader mr, TypeDefinition t) { // Enumerate custom attributes on the type definition @@ -45,19 +56,23 @@ static void PrintCustomAttributes(MetadataReader mr, TypeDefinition t) Console.WriteLine(); } } - // - public static void Run() + static void PrintTypesCustomAttributes(MetadataReader mr) { - using var fs = new FileStream(typeof(Program).Assembly.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using var peReader = new PEReader(fs); - MetadataReader mr = peReader.GetMetadataReader(); - - foreach(TypeDefinitionHandle tdh in mr.TypeDefinitions) + foreach (TypeDefinitionHandle tdh in mr.TypeDefinitions) { TypeDefinition t = mr.GetTypeDefinition(tdh); Console.WriteLine($"{mr.GetString(t.Namespace)}.{mr.GetString(t.Name)}"); PrintCustomAttributes(mr, t); } } + // + + public static void Run() + { + using var fs = new FileStream(typeof(Program).Assembly.Location, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var peReader = new PEReader(fs); + MetadataReader mr = peReader.GetMetadataReader(); + PrintTypesCustomAttributes(mr); + } }