Allow creating a MetadataFile with a MetadataReader / MetadataStringDecoder
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
MetadataReaderthat is shared byICSharpCode.Decompilerand code that runs outside of it -
ICSharpCode.Decompilerwill create a lot of extra string allocations in my program that could be avoided with the use ofMetadataStringDecoder
Solution
There are two potential ways this can be solved
- Add an optional
MetadataStringDecoderparameter to existing code paths that lead to the creation of aMetadataFile - Add an overload to
MetadataFilethat allows specifying an existingMetadataReaderdirectly
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