从 C# 8 中的 System.Reflection.Metadata 获取接口可为 null 的上下文元数据
Getting interface nullable context metadata from System.Reflection.Metadata in C# 8
我目前正在制作一个工具来处理新的 C# 8 可为 null 的上下文。基本上是我的项目的 API 批准工具。
我正在使用 System.Reflection.Metadata,只是在一种情况下提取元数据时遇到问题。
public class DerivedNullableBase2 : MyBase<MyBase<string?>?>
{
}
我正在尝试让 C#8 成为我正在创建的 API 生成器工具的可空上下文。所以对于上面的 class 生成以下 IL:
.class auto ansi nested public beforefieldinit DerivedNullableInterface2
extends [netstandard]System.Object
implements class [netstandard]System.Collections.Generic.IEnumerable`1<class [netstandard]System.Collections.Generic.IEnumerable`1<string>>,
[netstandard]System.Collections.IEnumerable
{
.interfaceimpl type class [netstandard]System.Collections.Generic.IEnumerable`1<class [netstandard]System.Collections.Generic.IEnumerable`1<string>>
.custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 00 02 00 00 )
} // end of class DerivedNullableInterface2
我想提取其中包含的 NullableAttribute 以确定通用接口的可为空上下文。
我试图通过 TypeDefinition 和 InterfaceImplementation 获取属性,但似乎不存在,在这种情况下我将如何提取 NullableAttribute?
以下代码将使用 C# 8 语法从 InterfaceImplementation
中提取 NullableAttribute
。
using var peReader = new PEReader(File.OpenRead(Assembly.GetExecutingAssembly().Location));
var mdReader = peReader.GetMetadataReader();
foreach (var attributeHandle in mdReader.CustomAttributes)
{
var attribute = mdReader.GetCustomAttribute(attributeHandle);
var ctorHandle = attribute.Constructor;
EntityHandle attributeTypeHandle = ctorHandle.Kind switch
{
HandleKind.MethodDefinition => mdReader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle).GetDeclaringType(),
HandleKind.MemberReference => mdReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent,
_ => throw new InvalidOperationException(),
};
StringHandle attributeTypeNameHandle = attributeTypeHandle.Kind switch
{
HandleKind.TypeDefinition => mdReader.GetTypeDefinition((TypeDefinitionHandle)attributeTypeHandle).Name,
HandleKind.TypeReference => mdReader.GetTypeReference((TypeReferenceHandle)attributeTypeHandle).Name,
_ => throw new InvalidOperationException(),
};
if (mdReader.StringComparer.Equals(attributeTypeNameHandle, "NullableAttribute"))
{
Console.WriteLine(attribute.Parent.Kind);
}
}
这是由https://github.com/dotnet/corefx/issues/40234#issuecomment-520254880
提供的
我目前正在制作一个工具来处理新的 C# 8 可为 null 的上下文。基本上是我的项目的 API 批准工具。
我正在使用 System.Reflection.Metadata,只是在一种情况下提取元数据时遇到问题。
public class DerivedNullableBase2 : MyBase<MyBase<string?>?>
{
}
我正在尝试让 C#8 成为我正在创建的 API 生成器工具的可空上下文。所以对于上面的 class 生成以下 IL:
.class auto ansi nested public beforefieldinit DerivedNullableInterface2
extends [netstandard]System.Object
implements class [netstandard]System.Collections.Generic.IEnumerable`1<class [netstandard]System.Collections.Generic.IEnumerable`1<string>>,
[netstandard]System.Collections.IEnumerable
{
.interfaceimpl type class [netstandard]System.Collections.Generic.IEnumerable`1<class [netstandard]System.Collections.Generic.IEnumerable`1<string>>
.custom instance void System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8[]) = ( 01 00 03 00 00 00 00 00 02 00 00 )
} // end of class DerivedNullableInterface2
我想提取其中包含的 NullableAttribute 以确定通用接口的可为空上下文。
我试图通过 TypeDefinition 和 InterfaceImplementation 获取属性,但似乎不存在,在这种情况下我将如何提取 NullableAttribute?
以下代码将使用 C# 8 语法从 InterfaceImplementation
中提取 NullableAttribute
。
using var peReader = new PEReader(File.OpenRead(Assembly.GetExecutingAssembly().Location));
var mdReader = peReader.GetMetadataReader();
foreach (var attributeHandle in mdReader.CustomAttributes)
{
var attribute = mdReader.GetCustomAttribute(attributeHandle);
var ctorHandle = attribute.Constructor;
EntityHandle attributeTypeHandle = ctorHandle.Kind switch
{
HandleKind.MethodDefinition => mdReader.GetMethodDefinition((MethodDefinitionHandle)ctorHandle).GetDeclaringType(),
HandleKind.MemberReference => mdReader.GetMemberReference((MemberReferenceHandle)ctorHandle).Parent,
_ => throw new InvalidOperationException(),
};
StringHandle attributeTypeNameHandle = attributeTypeHandle.Kind switch
{
HandleKind.TypeDefinition => mdReader.GetTypeDefinition((TypeDefinitionHandle)attributeTypeHandle).Name,
HandleKind.TypeReference => mdReader.GetTypeReference((TypeReferenceHandle)attributeTypeHandle).Name,
_ => throw new InvalidOperationException(),
};
if (mdReader.StringComparer.Equals(attributeTypeNameHandle, "NullableAttribute"))
{
Console.WriteLine(attribute.Parent.Kind);
}
}
这是由https://github.com/dotnet/corefx/issues/40234#issuecomment-520254880
提供的