【问题标题】:Why does a custom attribute appear both in IL and Metadata?为什么自定义属性会同时出现在 IL 和 Metadata 中?
【发布时间】:2011-04-02 09:46:59
【问题描述】:

有两个这样的属性:

[AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = true)]
sealed class Test1Attribute : Attribute
{ }

[AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = true)]
sealed class Test2Attribute : Attribute
{ }

它们很简单,什么都不做。

还有一个方法用这两个属性修饰:

public void Hello([Test1]string arg, [Test2] string arg2) { }

现在如果我用IL Dasm编译代码并反编译,我会看到方法“Hello”的IL代码是这样的:

.method public hidebysig instance void Hello(int32 arg, int32 arg2) cil managed
{
    .param [1]
    .custom instance void ConsoleApplication1.Test1Attribute::.ctor()
    .param [2]
    .custom instance void ConsoleApplication1.Test2Attribute::.ctor()
    .maxstack 8
    L_0000: nop 
    L_0001: ret 
}

我们可以看到 Test1Attribute 和 Test2Attribute 都在 IL 代码中。 它的元数据是这样的:

MethodName: Hello (06000005)
    Flags     : [Public] [HideBySig] [ReuseSlot]  (00000086)
    RVA       : 0x0000206b
    ImplFlags : [IL] [Managed]  (00000000)
    CallCnvntn: [DEFAULT]
    hasThis 
    ReturnType: Void
    2 Arguments
        Argument #1:  String
        Argument #2:  String
    2 Parameters
        (1) ParamToken : (08000002) Name : arg flags: [none] (00000000)
        CustomAttribute #1 (0c000010)
        -------------------------------------------------------
            CustomAttribute Type: 06000001
            CustomAttributeName: ConsoleApplication1.Test1Attribute :: instance void .ctor()
            Length: 4
            Value : 01 00 00 00                                      >                <
            ctor args: ()

        (2) ParamToken : (08000003) Name : arg2 flags: [none] (00000000)
        CustomAttribute #1 (0c000012)
        -------------------------------------------------------
            CustomAttribute Type: 06000002
            CustomAttributeName: ConsoleApplication1.Test2Attribute :: instance void .ctor()
            Length: 4
            Value : 01 00 00 00                                      >                <
            ctor args: ()

同样,这两个属性也在元数据中。

所以我很好奇:

  1. 为什么它们会同时出现在 IL 和元数据中?
  2. 是什么

    .param [1] .custom 实例无效 ConsoleApplication1.Test1Attribute::.ctor() .参数 [2] .custom 实例 void ConsoleApplication1.Test2Attribute::.ctor()

是什么意思?它看起来不像指令。那么它们是什么?他们是做什么的?

谢谢

【问题讨论】:

  • 不确定您的第一个问题:您想知道它们为什么会存在或为什么它们会出现在 IL元数据中?
  • 哦,我的意思是它们出现了两次,看起来有点冗长。

标签: .net metadata cil il


【解决方案1】:

属性只是一个类,请注意您使用 class 关键字来声明一个。每个类都有一个构造函数,即使你自己不写一个。构造方法的名称是 .ctor()。显然,对于任何方法,您都可以获得方法主体中代码的 IL。

方法的参数有自己的元数据。此处用于描述应用什么属性。 .param 指令给出参数编号,.custom 指令给出相关属性。这是 IL 语法中的注解,它实际上并不存在于方法 IL 中。

元数据结构复杂,包含数十个表,反汇编程序对其进行重写以使其更全面。如果您想了解它的真实外观,Ecma 335 拥有您所需的一切。

【讨论】:

    【解决方案2】:

    自定义属性是可以附加到大多数元数据的数据片段。如果您想要完整的详细信息 - 获取 ECMS 335 Spec 第 231 页有基础知识。第 242 页有关于 CustomAttribute 元数据表的信息,用于存储属性数据的序列化格式在第 295 页(所有页码都在实际的 pdf 文件页面中)。

    回答您的问题:

    1. 两方: 一种。您正在查看上述元数据的 2 个视图(1.带有方法(和参数)元数据的 IL 和 2.详细的元数据视图 - 减去 IL) 湾。 ILDasm 向您展示了需要执行的方法部分。您可能认为奇怪的是方法签名不包括属性 - 这是因为方法签名只是参数类型。附加到参数的任何属性都只是附加到参数而不是签名...所以 ILDasm 也会向您显示这些属性 - 但在签名下方。

    2. 这些是存储并附加到参数的属性的反序列化和连接的元数据。在您的情况下,它只是对默认构造函数的调用,但在更复杂的情况下,您将调用构造函数和数据参数,这些参数也存储在序列化位中。

    【讨论】:

      猜你喜欢
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2016-04-10
      • 1970-01-01
      • 2013-04-09
      相关资源
      最近更新 更多