From 45b7c47ef60242107e3db6fbb78e57c3ace1718f Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Tue, 24 Jan 2023 15:04:30 -0500 Subject: [PATCH] Move WebcilReader reflection to a helper; add lazy initialization --- .../src/Webcil/WebcilReader.Reflection.cs | 59 +++++++++++++++++++ .../src/Webcil/WebcilReader.cs | 34 ++--------- 2 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.Reflection.cs diff --git a/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.Reflection.cs b/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.Reflection.cs new file mode 100644 index 00000000000000..601dc5e5f66c89 --- /dev/null +++ b/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.Reflection.cs @@ -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 _readUtf8NullTerminated = new Lazy(() => + { + 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 _codeViewDebugDirectoryDataCtor = new Lazy(() => + { + 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 _pdbChecksumDebugDirectoryDataCtor = new Lazy(() => + { + var types = new Type[] { typeof(string), typeof(ImmutableArray) }; + 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 checksum) => (PdbChecksumDebugDirectoryData)_pdbChecksumDebugDirectoryDataCtor.Value.Invoke(new object[] { algorithmName, checksum }); + } +} diff --git a/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.cs b/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.cs index 95ad53e6e9a84a..39d58134ce6b48 100644 --- a/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.cs +++ b/src/libraries/Microsoft.NET.WebAssembly.Webcil/src/Webcil/WebcilReader.cs @@ -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, @@ -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 checksum) - { - var types = new Type[] { typeof(string), typeof(ImmutableArray) }; - 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 checksum) => Reflection.MakePdbChecksumDebugDirectoryData(algorithmName, checksum); public MetadataReaderProvider ReadEmbeddedPortablePdbDebugDirectoryData(DebugDirectoryEntry entry) {