如何只读取.net程序集中的元数据字节

时间:2018-02-17 14:21:45

标签: c# reflection metadata

由于Reflection只加载不再适用于.NET Core,我正在围绕System.Reflection.Metadata实现一个包装器,以允许我扫描一个程序集,查看它包含的类型,而不需要完整的程序集加载。

虽然MetadataReader基本上正在运行,但我实现如下:

 private unsafe MetadataReader LoadMetadataReader(
    string filename,
    MetadataReaderOptions options = MetadataReaderOptions.Default,
    MetadataStringDecoder decoder = null)
{
    buffer = File.ReadAllBytes(filename);
    pinnedHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
    var headers = new PEHeaders(new MemoryStream(buffer));
    var startOffset = headers.MetadataStartOffset;
    var metaDataStart = (byte*)pinnedHandle.AddrOfPinnedObject() + startOffset;
    return new MetadataReader(metaDataStart, headers.MetadataSize, options, decoder);
}

这意味着我每次都会为程序集加载所有字节。

我的问题是:是否有办法识别和加载读取元数据所需的文件中的字节子集?

1 个答案:

答案 0 :(得分:2)

感谢Hans Passant的评论,我解决了这个问题:

将程序集加载为Memory Mapped File

private static MemoryMappedFile LoadAssembly(string filename, out long length, out MemoryMappedFileAccess access)
{
    // Setup parameters to pass in
    return MemoryMappedFile.CreateFromFile(filename, mode, mapName, length, access);
}

创建MemoryMappedViewStream

using (var file = LoadAssembly(filename, out var length, out var access)) {
    using (var stream = file.CreateViewStream(0, length, access)) {

通过PEHeaders对象

从流中获取标题的尺寸
var headers = new PEHeaders(stream);

然后我能够从流中获取指向文件开头的实际指针并将其传递给MetadataReader构造函数

var start = (byte*)0;
stream.SafeMemoryMappedViewHandle.AcquirePointer(ref start);
var size = headers.MetadataSize;
var reader = new MetadataReader(start + headers.MetadataStartOffset, size, options, decoder);