Updated with a solution that works for me. See the bottom of this question.
Context:
I needed a way to evaluate the size of a generic type for the purpose of calculating array lengths to fit within a certain byte size. Basically,
sizeof
similar to what C/C++ provides.
C#'s sizeof
and Marshal.SizeOf are not suitable for this, because of their many limitations.
With this in mind, I wrote an assembly in IL that enables the functionality I was looking for through the sizeof
opcode. I'm aware that it essentially evaluates to IntPtr.Size
with reference types.
I duplicated this for .NET Standard & Core, referencing what I believed were the correct equivalents of mscorlib. Note that the IL compiles fine, this question is about another issue.
Code:
Headers per target framework:
.NET: (Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe)
.assembly extern mscorlib {}
.NET Standard: (ilasm extracted from nuget)
.assembly extern netstandard
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
.ver 0:0:0:0
}
.assembly extern System.Runtime
{
.ver 0:0:0:0
}
.NET Core: (same ilasm as standard, though I've tested with both)
.assembly extern System.Runtime
{
.ver 0:0:0:0
}
Source:
.assembly Company.IL
{
.ver 0:0:1:0
}
.module Company.IL.dll
// CORE is a define for mscorlib, netstandard, and System.Runtime
.class public abstract sealed auto ansi beforefieldinit
Company.IL.Embedded extends [CORE]System.Object
{
.method public hidebysig specialname rtspecialname instance void
.ctor() cil managed
{
.maxstack 8
ldarg.0
call instance void [CORE]System.Object::.ctor()
ret
}
.method public hidebysig static uint32
SizeOf<T>() cil managed
{
sizeof !!0
ret
}
}
Problem:
When any dll compiled in this manner is referenced by a .NET Core or Xamarin application, I receive the following error:
The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
This issue doesn't occur when such dlls are referenced by .NET projects or .NET standard libraries which are then referenced by a .NET project.
I've read countless articles, posts, and repositories detailing this error with different versions and assemblies. The typical solution seems to be to add an explicit reference to the target framework's equivalent of mscorlib(breaking portability). There seems to be a lack of information about using IL compiled assemblies for .NET Standard & Core.
To my understanding, .NET Standard & Core use facades that forward type definitions so they may be resolved by the target framework's runtime, enabling portability.
I've tried the following:
- Explicit versions of
System.Runtime
- Disassembling .NET Core libraries compiled from C#, using the exact same references. Oddly enough they seem to target explicit versions(such as System.Runtime 4.2 in .NET Core 2.0).
- Generating the code dynamically using the Emit API. Compiling to memory appears to work, but isn't an option because I'm also targeting Xamarin.iOS(AOT only). Referencing such dynamically compiled assemblies from disk results in the same error as if I compiled them manually.
Update:
I attempted the solution in Jacek's answer(following the build instructions here), yet couldn't configure my system to compile corefx with the build script or VS 2017. However, after digging through the code of System.Runtime.CompilerServices.Unsafe I discovered a solution.
This probably seems obvious, but I was referencing the wrong version of System.Runtime
.
Headers per target framework(copied from corefx):
.NET:
#define CORELIB "mscorlib"
.assembly extern CORELIB {}
.NET Standard:
#define CORELIB "System.Runtime"
#define netcoreapp
// Metadata version: v4.0.30319
.assembly extern CORELIB
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 4:0:0:0
}
.NET Core:
#define CORELIB "System.Runtime"
// Metadata version: v4.0.30319
.assembly extern CORELIB
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 4:0:0:0
}
In all source files, use CORELIB
to reference types in mscorlib(i.e. [CORELIB]System.Object
).
Reflection.Emit
attempt? – Lymphoid