0% found this document useful (0 votes)
53 views2 pages

Resources

System.Resources.ResourceReader is unsuitable for deserializing resources in ILSpy because it tries to deserialize custom resource types, which can fail if the types are in a non-GAC assembly. So a custom "ResourcesFile" class is used instead, based on the .NET Core ResourceReader implementation, to deserialize resources in a way that does not depend on type locations. The ResourcesFile class defines the format of the resource files, including headers for the resource manager and resource set, followed by name and value entries for each resource stored in a binary format.

Uploaded by

sp
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
53 views2 pages

Resources

System.Resources.ResourceReader is unsuitable for deserializing resources in ILSpy because it tries to deserialize custom resource types, which can fail if the types are in a non-GAC assembly. So a custom "ResourcesFile" class is used instead, based on the .NET Core ResourceReader implementation, to deserialize resources in a way that does not depend on type locations. The ResourcesFile class defines the format of the resource files, including headers for the resource manager and resource set, followed by name and value entries for each resource stored in a binary format.

Uploaded by

sp
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 2

System.Resources.

ResourceReader is unsuitable for deserializing resources in the


ILSpy context,
because it tries to deserialize custom resource types, which fails if the types are
in a non-GAC assembly.

So we are instead using our own "class ResourcesFile", which is based on the
.NET Core ResourceReader implementation.

struct ResourcesFileFormat {
int32 magicNum; [check == ResourceManager.MagicNumber]

// ResourceManager header:
int32 resMgrHeaderVersion; [check >= 0]
int32 numBytesToSkip; [check >= 0]
if (resMgrHeaderVersion <= 1) {
string readerType;
string resourceSetType;
} else {
byte _[numBytesToSkip];
}

// RuntimeResourceSet header:
int32 version; [check in (1, 2)]
int32 numResources; [check >=0]
int32 numTypes; [check >=0]
string typeName[numTypes];
.align 8;
int32 nameHashes[numResources];
int32 namePositions[numResources]; [check >= 0]
int32 dataSectionOffset; [check >= current position in file]
byte remainderOfFile[];
}

// normal strings in this file format are stored as:


struct string {
compressedint len;
byte value[len]; // interpret as UTF-8
}

// NameEntry #i is stored starting at remainderOfFile[namePositions[i]]


// (that is, namePositions is interpreted relative to the start of the
remainderOfFile array)
struct NameEntry {
compressedint len;
byte name[len]; // interpret as UTF-16
int32 dataOffset; [check >= 0]
}

// Found at position ResourcesFileFormat.dataSectionOffset+NameEntry.dataOffset in


the file.
struct ValueEntry {
if (version == 1) {
compressedint typeIndex;
if (typeIndex == -1) {
// no value stored; value is implicitly null
} else {
switch (typeName[typeIndex]) {
case string:
case int, uint, long, ulong, sbyte, byte, short, ushort:
case float:
case double:
T value; // value directly stored
case DateTime:
int64 value; // new DateTime(_store.ReadInt64())
case TimeSpan:
int64 value; // new TimeSpan(_store.ReadInt64())
case decimal:
int32 value[4];
default:
byte data[...]; // BinaryFormatter-serialized data
using typeName[typeIndex]
}
}
} else if (version == 2) {
compressedint typeCode;
// note: unlike v1, no lookup into the typeName array!
switch (typeCode) {
case null:
// no value stored; value is implicitly null
case string:
case bool:
case int, uint, long, ulong, sbyte, byte, short, ushort:
T value;
case char:
uint16 value;
case float:
case double:
case decimal:
T value;
case DateTime:
int64 value; // DateTime.FromBinary(_store.ReadInt64())
case TimeSpan:
int64 value; // new TimeSpan(_store.ReadInt64())
case ResourceTypeCode.ByteArray:
int32 len;
byte value[len];
case ResourceTypeCode.Stream:
int32 len;
byte value[len];
case >= ResourceTypeCode.StartOfUserTypes:
byte data[...]; // BinaryFormatter-serialized data using
typeName[typeCode - ResourceTypeCode.StartOfUserTypes]
}
}
}

You might also like