给定以下 3 个文件类:
file class MyClass
{
}
file class MyClass2
{
}
file class MyClass3
{
public int MyMember { get; init; }
}
通过反编译此 C# 代码,文件类现在如下所示:
internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass
{
}
internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass2
{
}
internal class <Class1>FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3__MyClass3
{
public int MyMember { get; init; }
}
我理解,
<Class1>
是定义文件类的源文件的名称,MyClass...
是文件类的名称。
我不明白的是这很长,看似两者之间的ID:
FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3
据我了解,它似乎根据源文件名而有所不同,当两个尖括号之间的文本
<Class1>
似乎已经发挥作用时,这是令人惊讶的。
C#编译器如何产生这个ID?我在互联网上找不到任何相关信息。
我决定进一步挖掘 Roslyn 的源代码。使用临时自动化工具查找每个包含
FileLocalType
的 C# 源文件,大约有 12 个 C# 源文件。
终于,我来到了这里。生成此ID的代码:
internal static string MakeFileTypeMetadataNamePrefix(string filePath, ImmutableArray<byte> checksumOpt)
{
var pooledBuilder = PooledStringBuilder.GetInstance();
var sb = pooledBuilder.Builder;
sb.Append('<');
AppendFileName(filePath, sb);
sb.Append('>');
sb.Append((char)GeneratedNameKind.FileType);
if (checksumOpt.IsDefault)
{
// Note: this is an error condition.
// This is only included for clarity for users inspecting the value of 'MetadataName'.
sb.Append("<no checksum>");
}
else
{
foreach (var b in checksumOpt)
{
sb.AppendFormat("{0:X2}", b);
}
}
sb.Append("__");
return pooledBuilder.ToStringAndFree();
}
定义于here。
进一步查看后,这才是真正的ID。 这里的神秘ID是定义文件类的源文件的名称,使用SHA256哈希算法加密。这确实不容易找到。是的,我确实需要这个算法,而不是仅仅生成一个随机整数,然后对结果进行字符串化,这将是执行此操作的传统方法,但是,这回答了问题。