Skip to content

Commit

Permalink
Move WebcilReader reflection to a helper; add lazy initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
lambdageek committed Jan 24, 2023
1 parent 6eaee63 commit 45b7c47
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Immutable;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

namespace Microsoft.NET.WebAssembly.Webcil;


public sealed partial class WebcilReader
{

// Helpers to call into System.Reflection.Metadata internals
internal static class Reflection
{
private static Lazy<MethodInfo> _readUtf8NullTerminated = new Lazy<MethodInfo>(() =>
{
var mi = typeof(BlobReader).GetMethod("ReadUtf8NullTerminated", BindingFlags.NonPublic | BindingFlags.Instance);
if (mi == null)
{
throw new InvalidOperationException("Could not find BlobReader.ReadUtf8NullTerminated");
}
return mi;
});

internal static string? ReadUtf8NullTerminated(BlobReader reader) => (string?)_readUtf8NullTerminated.Value.Invoke(reader, null);

private static Lazy<ConstructorInfo> _codeViewDebugDirectoryDataCtor = new Lazy<ConstructorInfo>(() =>
{
var types = new Type[] { typeof(Guid), typeof(int), typeof(string) };
var mi = typeof(CodeViewDebugDirectoryData).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
if (mi == null)
{
throw new InvalidOperationException("Could not find CodeViewDebugDirectoryData constructor");
}
return mi;
});

internal static CodeViewDebugDirectoryData MakeCodeViewDebugDirectoryData(Guid guid, int age, string path) => (CodeViewDebugDirectoryData)_codeViewDebugDirectoryDataCtor.Value.Invoke(new object[] { guid, age, path });

private static Lazy<ConstructorInfo> _pdbChecksumDebugDirectoryDataCtor = new Lazy<ConstructorInfo>(() =>
{
var types = new Type[] { typeof(string), typeof(ImmutableArray<byte>) };
var mi = typeof(PdbChecksumDebugDirectoryData).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
if (mi == null)
{
throw new InvalidOperationException("Could not find PdbChecksumDebugDirectoryData constructor");
}
return mi;
});
internal static PdbChecksumDebugDirectoryData MakePdbChecksumDebugDirectoryData(string algorithmName, ImmutableArray<byte> checksum) => (PdbChecksumDebugDirectoryData)_pdbChecksumDebugDirectoryDataCtor.Value.Invoke(new object[] { algorithmName, checksum });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace Microsoft.NET.WebAssembly.Webcil;


public sealed class WebcilReader : IDisposable
public sealed partial class WebcilReader : IDisposable
{
// WISH:
// This should be implemented in terms of System.Reflection.Internal.MemoryBlockProvider like the PEReader,
Expand Down Expand Up @@ -219,37 +219,11 @@ private static CodeViewDebugDirectoryData DecodeCodeViewDebugDirectoryData(BlobR
return MakeCodeViewDebugDirectoryData(guid, age, path);
}

private static string? ReadUtf8NullTerminated(BlobReader reader)
{
var mi = typeof(BlobReader).GetMethod("ReadUtf8NullTerminated", BindingFlags.NonPublic | BindingFlags.Instance);
if (mi == null)
{
throw new InvalidOperationException("Could not find BlobReader.ReadUtf8NullTerminated");
}
return (string?)mi.Invoke(reader, null);
}
private static string? ReadUtf8NullTerminated(BlobReader reader) => Reflection.ReadUtf8NullTerminated(reader);

private static CodeViewDebugDirectoryData MakeCodeViewDebugDirectoryData(Guid guid, int age, string path)
{
var types = new Type[] { typeof(Guid), typeof(int), typeof(string) };
var mi = typeof(CodeViewDebugDirectoryData).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
if (mi == null)
{
throw new InvalidOperationException("Could not find CodeViewDebugDirectoryData constructor");
}
return (CodeViewDebugDirectoryData)mi.Invoke(new object[] { guid, age, path });
}
private static CodeViewDebugDirectoryData MakeCodeViewDebugDirectoryData(Guid guid, int age, string path) => Reflection.MakeCodeViewDebugDirectoryData(guid, age, path);

private static PdbChecksumDebugDirectoryData MakePdbChecksumDebugDirectoryData(string algorithmName, ImmutableArray<byte> checksum)
{
var types = new Type[] { typeof(string), typeof(ImmutableArray<byte>) };
var mi = typeof(PdbChecksumDebugDirectoryData).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, types, null);
if (mi == null)
{
throw new InvalidOperationException("Could not find PdbChecksumDebugDirectoryData constructor");
}
return (PdbChecksumDebugDirectoryData)mi.Invoke(new object[] { algorithmName, checksum });
}
private static PdbChecksumDebugDirectoryData MakePdbChecksumDebugDirectoryData(string algorithmName, ImmutableArray<byte> checksum) => Reflection.MakePdbChecksumDebugDirectoryData(algorithmName, checksum);

public MetadataReaderProvider ReadEmbeddedPortablePdbDebugDirectoryData(DebugDirectoryEntry entry)
{
Expand Down

0 comments on commit 45b7c47

Please sign in to comment.