Быстрый ответ
Ресурсы, которые вы добавляете в программу на C #, хранятся в разделе ресурсов двоичного файла PE.
Например, если я добавлю строку, MyTestString
, со значением "Charles is Cool"
Если я откроюСкомпилированный двоичный файл в шестнадцатеричном редакторе, я вижу свою строку:
Круто, но как это здесь получилось?
Сторона C #
Редактор ресурсов генерирует Resources.Designer.cs, вот что он сгенерировал
/// <summary>
/// Looks up a localized string similar to Charles is Cool.
/// </summary>
internal static string MyTestString {
get {
return ResourceManager.GetString("MyTestString", resourceCulture);
}
}
Но подождите ... Я не вижу "Charles is Cool"
где-нибудь здесь ..Куда это делось?Откуда GetString()
получает его?
Ну, в конце концов, он унижает ресурс (терминология MSFT, а не моя), я полагаю, нам следует рассмотреть это ManifestBasedResourceGroveler
, которое в конечном итоге получитнам extern GetResource()
, верный признак того, что мы упали с края вселенной .NET ... вы знаете, что это означает ...
Сторона CoreCLR
Мы можем посмотреть в репозитории coreclr пример того, как это реализовано,
Если вы проследите код здесь, вы в конечном итоге получите PEDecoder::GetResource()
const void *PEDecoder::GetResource(COUNT_T offset, COUNT_T *pSize) const
{
CONTRACT(const void *)
{
INSTANCE_CHECK;
PRECONDITION(CheckCorHeader());
PRECONDITION(CheckPointer(pSize, NULL_OK));
NOTHROW;
GC_NOTRIGGER;
}
CONTRACT_END;
IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->Resources;
// 403571: Prefix complained correctly about need to always perform rva check
if (CheckResource(offset) == FALSE)
return NULL;
void * resourceBlob = (void *)GetRvaData(VAL32(pDir->VirtualAddress) + offset);
// Holds if CheckResource(offset) == TRUE
PREFIX_ASSUME(resourceBlob != NULL);
if (pSize != NULL)
*pSize = GET_UNALIGNED_VAL32(resourceBlob);
RETURN (const void *) ((BYTE*)resourceBlob+sizeof(DWORD));
}
Который в основном находит смещение от заголовка PE (см. IMAGE_COR20_HEADER
).Прочтите статью Portable Executable в Википедии , вы увидите, что в образе svg есть раздел для ResourceTable (RVA, он же Относительный виртуальный адрес )
What I 'Суть в том, что Ресурсы ни в коем случае не являются функцией C # или .NET, это всего лишь управляемый API, который всегда был в двоичном формате PE.
Для произвольных бинарных ресурсов
Обратите внимание, что все, что я сказал, работает для произвольных данных, если вы добавите какой-нибудь двоичный файл в ваши ресурсы, Resources
представит его вам как byte[]
но на самом деле это закодировало бы его как-то еще.
Открывая файл resx в Visual Studio, вы получаете довольно неинтересный путь к импортированному вами двоичному файлу, обратите внимание, что если вы откроете скомпилированный двоичный файл вчто-то вроде JetBrains DotPeek и посмотрите на файл resx, путь к файлу был заменен строкой,
<data name="binary" type="System.Byte[], mscorlib">
<value>CGdTCb7vyv7AD/6rze8=</value>
</data>
Хотя я не смог найти никакого кода на VisualСтудия, чтобы доказать это, я бы предположил, что эта строка представляет собой версию байтов в (двоичном) файле ресурсов в кодировке base64, потому что запуск Convert.ToBase64String(Resources.binary)
дает мне ту же строку, что и в файле resx скомпилированного двоичного файла.Для тех из вас, кто хочет попробовать это дома, мой бинарный файл содержит 08 67 53 09 BE EF CA FE C0 0F FE AB CD EF
.