c# - 从 C# 8 中的 System.Reflection.Metadata 获取接口(interface)可为 null 的上下文元数据

标签 c# .net cil

我目前正在制作一个工具来处理新的 C# 8 可空上下文。基本上是我的项目的 API 审批工具。

我正在使用 System.Reflection.Metadata,只是在一种情况下提取元数据时遇到问题。

public class DerivedNullableBase2 : MyBase<MyBase<string?>?>
{
}

我正在尝试为我正在创建的 API 生成器工具获取 C#8 可为空上下文。因此,对于上面的类,会生成以下 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 以确定通用接口(interface)的可为空上下文。

我尝试通过 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# - 从 C# 8 中的 System.Reflection.Metadata 获取接口(interface)可为 null 的上下文元数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57445665/

相关文章:

c# - 如何使用 Storyboard为 Stackpanel 的边距设置动画?

C# 编码(marshal) uint*& 参数

c# - BigInteger.ToString ("x") 没有正确打印负十六进制数

.net - 如何找到泛型参数的 TypeSpec

c++-cli - VS2015 C++/CLI Release Build 中的 NullReferenceException

c# - 在 C# 中为所有事件和委托(delegate)创建一个包罗万象的处理程序

c# - C# 中的静态抽象方法

c# - 如何将 "any non-nullable type"指定为泛型类型参数约束?

c# - 将属性映射到集合项

c# - xsl 格式日期(子字符串 + 连接?)