Подтвердить что ты не робот

Как Reflection реализован в С#?

Мне было любопытно, где Type.GetType() реализован, поэтому я заглянул в сборку и заметил Type.GetType() calls base.GetType(), и поскольку Type наследует от MemberInfo, я взглянул и определился как _MemberInfo.GetType(), который возвращает this.GetType(). Поскольку я не могу найти фактический код, который показывает, как С# может получить информацию о типе, которую я хотел бы знать:

Как CLR получает Type и MemberInfo из объектов в Runtime?

4b9b3361

Ответ 1

Источник ACTUAL для .NET Framework 2.0 доступен в Интернете (для образовательных целей) здесь: http://www.microsoft.com/en-us/download/details.aspx?id=4917

Это реализация языка С#. Вы можете использовать 7zip, чтобы распаковать его. Вы найдете пространство имен отражения здесь (относительно):

.\Sscli20\CLR\SRC\Bcl\система\отражения

Я копаю для конкретной реализации, о которой вы просите, но это хороший старт.

ОБНОВЛЕНИЕ: Извините, но я думаю, что это тупик. Type.GetType() вызывает базовую реализацию, которая поступает из System.Object. Если вы проверите этот код (.\sscli20\clr\src\bcl\system\object.cs), вы найдете способ extern (см. Код ниже). Дальнейшая проверка может выявить реализацию, но ее не в BCL. Я подозреваю, что это будет где-то в коде С++.

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

UPDATE (AGAIN): Я углубился и нашел ответ в реализации самой виртуальной машины CLR. (Его в С++).

Первая часть головоломки находится здесь:

\ sscli20\CLR\SRC\ут\ecall.cpp

Здесь мы видим код, который отображает внешний вызов функции С++.

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

Теперь нам нужно найти find ObjectNative::GetClass... который находится здесь:

\ sscli20\CLR\SRC\ут\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\ут\object.cpp

Ответ 2

Наиболее значимые части отражения реализованы как часть самой CLI. Таким образом, вы можете посмотреть или справочный источник MS CLI (он же "Ротор" ), или моно источник. Но: в основном это C/С++. Подробности реализации публичного API (MethodInfo, Type и т.д.) Могут быть С#.

Ответ 3

Это может не ответить на ваш вопрос напрямую. Тем не менее, вот немного очертания того, как управляемый код знает все о типах.

  • Всякий раз, когда вы компилируете код, компилятор анализирует/анализирует исходные файлы и собирает информацию, с которой он сталкивается. Например, взгляните на класс ниже.

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

    Компилятор может видеть, что это внутренний класс с двумя членами. Member one является свойством типа int с приватным сетевым устройством. Member 2 - защищенный метод с именем Met2 и тип boolean, который принимает ввод с плавающей точкой (имя входа - "вход" ). Итак, у него есть вся эта информация.

  • Сохраняет эту информацию в сборке. Есть пара столов. Например, классы (типы) все выходят в одной таблице, методы живут в другой таблице. Подумайте в туре таблиц SQL, хотя они определенно не являются.

  • Когда пользователь (разработчик) хочет знать информацию о типе, он вызывает метод GetType. Этот метод основан на указателе объекта скрытого типа объекта. Этот объект в основном является указателем на таблицу классов. Каждая таблица классов будет иметь указатель на первый метод в таблице методов. Каждая запись метода будет иметь указатель на первый параметр в таблице параметров.

PS: этот механизм зависит от того, как сделать сборки .NET более безопасными. Вы не можете заменить указатели на методы. Это нарушит подпись assebmly.

JIT-компиляция также сильно зависит от этих таблиц

Ответ 4

Как указывает @GlennFerrieLive, вызов GetType является InternalCall, что означает, что реализация находится внутри самой среды CLR, а не в любом из BCL.

Я понимаю, что внутренний метод CLR принимает информацию типа времени выполнения из указателя this, который в основном соответствует имени типа. Затем он просматривает полную информацию о типе из метаданных, присутствующих во всех загруженных сборках (предположительно, в текущем appdomain), что делает отражение довольно дорогостоящим. Область метаданных представляет собой базу данных всех типов и элементов, присутствующих в сборке, и создает из этих данных экземпляр Type или Method|Property|FieldInfo.