JsonSerializerOptions.MemberAccessorStrategy shouldn't use Reflection.Emit when IsDynamicCodeCompiled is false (original) (raw)
When trimming a Blazor WASM app, the last usage of Reflection.Emit (after fixing #38678) is coming from System.Text.Json.Serialization.JsonSerializerOptions:
internal MemberAccessor MemberAccessorStrategy |
---|
{ |
get |
{ |
if (_memberAccessorStrategy == null) |
{ |
#if NETFRAMEWORK | |
_memberAccessorStrategy = new ReflectionEmitMemberAccessor(); |
#else |
_memberAccessorStrategy = new ReflectionMemberAccessor(); |
#endif |
} |
return _memberAccessorStrategy; |
} |
} |
However, on Mono WASM, RuntimeFeature.IsDynamicCodeCompiled
is always false, so using Reflection.Emit is probably a waste, and it brings in a decent amount of code. In my investigations I find it removing ~50KB of IL if we trim this usage of Reflection.Emit.
We should change this code to something more like:
internal MemberAccessor MemberAccessorStrategy
{
get
{
if (_memberAccessorStrategy == null)
{
#if NETFRAMEWORK || NETCOREAPP if (RuntimeFeature.IsDynamicCodeCompiled) { _memberAccessorStrategy = new ReflectionEmitMemberAccessor(); } else { _memberAccessorStrategy = new ReflectionMemberAccessor(); } #else _memberAccessorStrategy = new ReflectionMemberAccessor(); #endif }
return _memberAccessorStrategy;
}
}
With changing the code to the above, on a default template Blazor WASM app, I am seeing size savings of:
Build | Size |
---|---|
master | 3,366,912 bytes |
#38729 | 3,039,232 bytes |
#38729 + this change | 2,990,080 bytes |
So almost a 50 KB savings by allowing the removing all usages of System.Reflection.Emit.