20

がどこに実装されているのか気になったので、アセンブリを覗いて呼び出しにType.GetType()気付きました。C# がどのように型情報を取得できるかを示す実際のコードが見つからないので、知りたいのですが:Type.GetType()base.GetType()TypeMemberInfo_MemberInfo.GetType()this.GetType()

CLR はどのように実行時にオブジェクトから Type と MemberInfo を取得しますか?

4

4 に答える 4

16

.NET Framework 2.0 の実際のソースは、インターネット (教育目的) で入手できます: http://www.microsoft.com/en-us/download/details.aspx?id=4917

これは C# 言語の実装です。7zip を使用して解凍できます。リフレクションの名前空間は (相対的に) ここにあります。

.\sscli20\clr\src\bcl\system\reflection

あなたが求めている特定の実装を探していますが、これは良いスタートです。

更新:申し訳ありませんが、行き止まりだと思います。 Type.GetType()System.Object から来る基本実装への呼び出し。そのコードファイル ( .\sscli20\clr\src\bcl\system\object.cs) を調べると、メソッドがextern(以下のコードを参照) であることがわかります。さらに調査すると実装が明らかになる可能性がありますが、BCL にはありません。どこかの C++ コードになると思います。

// Returns a Type object which represent this object instance.
// 
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern Type GetType();

更新 (再度):私はさらに深く掘り下げ、CLR 仮想マシン自体の実装に答えを見つけました。(その C++ で)。

パズルの最初のピースは次のとおりです。

\sscli20\clr\src\vm\ecall.cpp

ここでは、外部呼び出しを C++ 関数にマップするコードを示します。

FCFuncStart(gObjectFuncs)
    FCIntrinsic("GetType", ObjectNative::GetClass, CORINFO_INTRINSIC_Object_GetType)
    FCFuncElement("InternalGetHashCode", ObjectNative::GetHashCode)
    FCFuncElement("InternalEquals", ObjectNative::Equals)
    FCFuncElement("MemberwiseClone", ObjectNative::Clone)
FCFuncEnd()

今、私たちは探しに行く必要がありますObjectNative::GetClass...それはここにあります:

\sscli20\clr\src\vm\comobject.cpp

の実装は次のGetTypeとおりです。

    FCIMPL1(Object*, ObjectNative::GetClass, Object* pThis)
{
    CONTRACTL
    {
        THROWS;
        SO_TOLERANT;
        DISABLED(GC_TRIGGERS); // FCallCheck calls ForbidenGC now
        INJECT_FAULT(FCThrow(kOutOfMemoryException););
        SO_TOLERANT;
        MODE_COOPERATIVE;
    }
    CONTRACTL_END;

    OBJECTREF   objRef   = ObjectToOBJECTREF(pThis);
    OBJECTREF   refType  = NULL;
    TypeHandle  typeHandle = TypeHandle();

    if (objRef == NULL) 
        FCThrow(kNullReferenceException);

    typeHandle = objRef->GetTypeHandle();
    if (typeHandle.IsUnsharedMT())
        refType = typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();
    else
        refType = typeHandle.GetManagedClassObjectIfExists();

    if (refType != NULL)
        return OBJECTREFToObject(refType);

    HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_RETURNOBJ, objRef, refType);

    if (!objRef->IsThunking())
        refType = typeHandle.GetManagedClassObject();
    else
        refType = CRemotingServices::GetClass(objRef);
    HELPER_METHOD_FRAME_END();

    return OBJECTREFToObject(refType);
}
FCIMPLEND

最後に、 の実装とGetTypeHandleその他のサポート機能は、次の場所にあります。

\sscli20\clr\src\vm\object.cpp

于 2013-03-02T04:33:21.533 に答える
7

リフレクションの最も重要な部分は、CLI自体の一部として実装されます。そのため、 MS CLIリファレンスソース(別名「ローター」)またはモノラルソースのいずれかを確認できます。ただし、ほとんどはC /C++になります。パブリックAPI実装の詳細(MethodInfoなどType)はC#の場合があります。

于 2013-02-27T07:47:02.227 に答える
5

それはあなたの質問に直接答えないかもしれません。ただし、ここでは、マネージコードが型についてすべてを知る方法の概要を説明します。

  1. コードをコンパイルするたびに、コンパイラはソースファイルを分析/解析し、検出した情報を収集します。たとえば、以下のクラスを見てください。

    class A
    {
      public int Prop1 {get; private set;}
      protected bool Met2(float input) {return true;}
    }
    

    コンパイラーは、これが2つのメンバーを持つ内部クラスであることを確認できます。メンバー1は、プライベートセッターを持つint型のプロパティです。メンバー2は、名前がMet2で、float入力を受け取るタイプbooleanの保護されたメソッドです(入力名は'input'です)。だから、それはすべてのこの情報を持っています。

  2. この情報をアセンブリに保存します。いくつかのテーブルがあります。たとえば、クラス(タイプ)はすべて1つのテーブルに残され、メソッドは別のテーブルに存在します。確かにそうではありませんが、SQLテーブルの混乱を考えてみてください。

  3. ユーザー(開発者)がタイプに関する情報を知りたい場合は、GetTypeメソッドを呼び出します。このメソッドは、オブジェクトの非表示フィールド(オブジェクトポインタ型)に依存しています。このオブジェクトは基本的にクラステーブルへのポインタです。各クラステーブルには、メソッドテーブルの最初のメソッドへのポインタがあります。各メソッドレコードには、パラメータテーブルの最初のパラメータへのポインタがあります。

PS:このメカニズムは、.NETアセンブリをより安全にするための鍵です。メソッドへのポインタを置き換えることはできません。それはアセンブリの署名を壊します。

JITコンパイルもこのテーブルに大きく依存しています

于 2013-03-03T03:57:09.700 に答える
2

@GlennFerrieLiveが指摘しているように、GetTypeの呼び出しInternalCallは、実装がCLR自体の内部にあり、BCLのいずれにも含まれていないことを意味します。

私の理解では、内部CLRメソッドは、thisポインターから実行時型情報を取得します。これは、基本的に型の名前に相当します。次に、ロードされたすべてのアセンブリ(おそらく現在のappdomain)に存在するメタデータから完全な型情報を検索します。これにより、リフレクションがかなり高価になります。メタデータ領域は基本的に、アセンブリに存在するすべてのタイプとメンバーのデータベースであり、このデータのインスタンスTypeまたはMethod|Property|FieldInfoこのデータからインスタンスを構築します。

于 2013-03-02T05:32:52.817 に答える