ILSpy icon indicating copy to clipboard operation
ILSpy copied to clipboard

Allow creating a MetadataFile with a MetadataReader / MetadataStringDecoder

Open lordmilko opened this issue 8 months ago • 0 comments

Problem

System.Reflection.Metadata allows specifying a System.Reflection.Metadata.MetadataStringDecoder to your MetadataReader to cache any strings it allocates, thereby reducing allocations.

I have an existing MetadataReader that is using my custom MetadataStringDecoder, however ICSharpCode.Decompiler.Metadata.MetadataFile does not allow me to pass in my existing MetadataReader, it instead requires that I pass in a System.Reflection.Metadata.MetadataReaderProvider.

If MetadataReaderProvider.GetMetadataReader is called multiple times with the same inputs, the same MetadataReader will be returned each time. I thought that maybe I could create a MetadataReaderProvider to get the MetadataReader that I and ICSharpCode.Decompiler both need to use, however GetMetadataReader does not return its cached MetadataReader if it is called multiple times with different arguments. GetMetadataReader allows specifying a MetadataStringDecoder to it, however, ICSharpCode.Decompiler does not support this, which means

  • it's not possible for me to have a single MetadataReader that is shared by ICSharpCode.Decompiler and code that runs outside of it
  • ICSharpCode.Decompiler will create a lot of extra string allocations in my program that could be avoided with the use of MetadataStringDecoder

Solution

There are two potential ways this can be solved

  • Add an optional MetadataStringDecoder parameter to existing code paths that lead to the creation of a MetadataFile
  • Add an overload to MetadataFile that allows specifying an existing MetadataReader directly

The former approach works well with the PEReader type, which derives from MetadataFile, while the latter works better when you're handling PE parsing yourself and want to interact with MetadataFile directly. As such, I have implemented both approaches.

utf8Decoder is the name that System.Reflection.Metadata gives to MetadataStringDecoder parameters, so I have used the same name

lordmilko avatar Jun 01 '25 04:06 lordmilko