给定以下 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();
}
进一步观察后,我可以推断 这里的神秘 ID 是定义文件类的源文件的完整(绝对)路径,使用 SHA256 哈希算法进行哈希处理(有时显然是 SHA1,但默认情况下是 SHA256)。 是的,我确实需要这个算法而不是仅仅生成一个随机整数然后对结果进行字符串化,这将是执行此操作的传统方法,但是,这回答了问题。
由于某种原因,这些 ID 前面带有“F”,因为这行代码位于同一个
MakeFileTypeMetadataNamePrefix
方法中:
sb.Append('>');
/*HERE -->*/sb.Append((char)GeneratedNameKind.FileType);
if (checksumOpt.IsDefault)
就我而言,这里是这个长哈希字符串:
FFEAE62924BA736A3C9E8DE39EA3099D227B65B02C0A6BC7FECCB5FF0D5B9D8B3
是使用 SHA256 算法对该字符串进行哈希处理的结果,其结果前面带有“F”:
C:\Users\User\source\repos\TemporaryAppRepository\FileClassTest\Class1.cs