All right, I'll answer my own question.
I've found no evidence that the System.Reflection.Emit
APIs can generate assemblies referencing another version of mscorlib
than the one used used by the current process. Indeed, the APIs that take System.Type
parameters and other reflection objects presumably add a reference to the result of querying their Type.Assembly
property, which corresponds to the version of mscorlib
in use.
However, portable class libraries aren't that different from what System.Reflection.Emit
generates, so it is possible to patch the assemblies after the fact to "make them portable". Disclaimer: this requires familiarity with the PE file format and might have unforeseen side-effects, but it works for me:
When generating the assembly, use AssemblyBuilder.SetCustomAttribute
to add this attribute to the assembly:
[System.Runtime.Versioning.TargetFrameworkAttribute(".NETPortable,Version=v4.0,Profile=Profile136", FrameworkDisplayName = ".NET Portable Subset")]
This is where it gets sketchy: after having called AssemblyBuilder.Save
, open a read/write file stream to the generated assembly, walk through the PE, COFF, COM, CLI and metadata table headers to locate the AssemblyRef
table row for mscorlib
. Modify the referenced version of mscorlib
to 2.0.5.0
, add 0x100
to its flags ("retargetable") and update its public key token blob to 0x7CEC85D7BEA7798E
.
Note that if you use other framework assemblies, you might need to patch their references as well (I haven't tested this). Otherwise, voilà! The assembly is now portable and can be used, for example, in a Windows Phone project.
(... or just use Mono.Cecil
/IKVM.Reflection
...)
Edit: The code I used can be found on github. This is a huge hack so the usual disclaimers apply, use at your own risks.