4

次のような 2 つの属性があります。

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

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

それらは非常に単純で、何もしません。

そして、これら 2 つの属性で装飾されたメソッドがあります。

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 インスタンス void ConsoleApplication1.Test1Attribute::.ctor() .param [2] .custom インスタンス void ConsoleApplication1.Test2Attribute::.ctor()

平均?指導のようには見えません。それで、彼らは何ですか?彼らは何をしますか?

ありがとう

4

2 に答える 2

4

属性は単なるクラスです。classキーワードを使用して宣言したことに注意してください。自分でコンストラクターを作成しなくても、すべてのクラスにコンストラクターがあります。コンストラクターメソッドの名前は.ctor()です。明らかに、どのメソッドでも、メソッド本体のコードのILを取得します。

メソッドのパラメーターには、独自のメタデータがあります。ここでは、適用される属性を説明するために使用されます。.paramディレクティブはパラメーター番号を示し、.customディレクティブは関連する属性を示します。これはIL構文の注釈であり、メソッドIL内には物理的に存在しません。

メタデータ構造は数十のテーブルで洗練されており、逆アセンブラはそれをより包括的にするために書き直します。 Ecma 335には、実際にどのように見えるかを知りたい場合に必要なものがすべて揃っています。

于 2011-04-02T12:24:05.543 に答える
4

カスタム属性は、ほとんどすべてのメタデータに添付できるデータです。完全な詳細が必要な場合は、ECMS 335 Spec Page 231 を入手してください。242 ページには、CustomAttribute メタデータ テーブルに関する情報があり、属性データの格納に使用されるシリアル化形式は 295 ページにあります (すべてのページ番号は、実際の pdf ファイル ページにあります)。

質問への回答:

  1. 2 人: a. 上記のメタデータの 2 つのビューが表示されています (1. メソッド (およびパラメーター) メタデータを含む IL、および 2. 詳細なメタデータ ビュー - IL を除く) b. ILDasm は、実行に必要なメソッドの部分を示します。奇妙に思われるかもしれませんが、メソッド シグネチャに属性が含まれていないということです。これは、メソッド シグネチャが単なるパラメータ タイプであるためです。パラメータに添付された属性は、パラメータに添付されたものであり、署名ではありません...したがって、ILDasmはそれらも表示しますが、署名の下にあります。

  2. これらは、保存され、パラメーターに添付された属性の逆シリアル化され、接続されたメタデータです。あなたの場合、それはデフォルトのコンストラクターへの単なる呼び出しですが、より複雑なケースでは、シリアライズされたビットにも格納されたコンストラクターとデータパラメーターへの呼び出しがあります。

于 2011-04-02T12:45:12.830 に答える