がどこに実装されているのか気になったので、アセンブリを覗いて呼び出しにType.GetType()
気付きました。C# がどのように型情報を取得できるかを示す実際のコードが見つからないので、知りたいのですが:Type.GetType()
base.GetType()
Type
MemberInfo
_MemberInfo.GetType()
this.GetType()
CLR はどのように実行時にオブジェクトから Type と MemberInfo を取得しますか?
.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
リフレクションの最も重要な部分は、CLI自体の一部として実装されます。そのため、 MS CLIリファレンスソース(別名「ローター」)またはモノラルソースのいずれかを確認できます。ただし、ほとんどはC /C++になります。パブリックAPI実装の詳細(MethodInfo
などType
)はC#の場合があります。
それはあなたの質問に直接答えないかもしれません。ただし、ここでは、マネージコードが型についてすべてを知る方法の概要を説明します。
コードをコンパイルするたびに、コンパイラはソースファイルを分析/解析し、検出した情報を収集します。たとえば、以下のクラスを見てください。
class A
{
public int Prop1 {get; private set;}
protected bool Met2(float input) {return true;}
}
コンパイラーは、これが2つのメンバーを持つ内部クラスであることを確認できます。メンバー1は、プライベートセッターを持つint型のプロパティです。メンバー2は、名前がMet2で、float入力を受け取るタイプbooleanの保護されたメソッドです(入力名は'input'です)。だから、それはすべてのこの情報を持っています。
この情報をアセンブリに保存します。いくつかのテーブルがあります。たとえば、クラス(タイプ)はすべて1つのテーブルに残され、メソッドは別のテーブルに存在します。確かにそうではありませんが、SQLテーブルの混乱を考えてみてください。
ユーザー(開発者)がタイプに関する情報を知りたい場合は、GetTypeメソッドを呼び出します。このメソッドは、オブジェクトの非表示フィールド(オブジェクトポインタ型)に依存しています。このオブジェクトは基本的にクラステーブルへのポインタです。各クラステーブルには、メソッドテーブルの最初のメソッドへのポインタがあります。各メソッドレコードには、パラメータテーブルの最初のパラメータへのポインタがあります。
PS:このメカニズムは、.NETアセンブリをより安全にするための鍵です。メソッドへのポインタを置き換えることはできません。それはアセンブリの署名を壊します。
JITコンパイルもこのテーブルに大きく依存しています
@GlennFerrieLiveが指摘しているように、GetTypeの呼び出しInternalCall
は、実装がCLR自体の内部にあり、BCLのいずれにも含まれていないことを意味します。
私の理解では、内部CLRメソッドは、this
ポインターから実行時型情報を取得します。これは、基本的に型の名前に相当します。次に、ロードされたすべてのアセンブリ(おそらく現在のappdomain)に存在するメタデータから完全な型情報を検索します。これにより、リフレクションがかなり高価になります。メタデータ領域は基本的に、アセンブリに存在するすべてのタイプとメンバーのデータベースであり、このデータのインスタンスType
またはMethod|Property|FieldInfo
このデータからインスタンスを構築します。