ILPack icon indicating copy to clipboard operation
ILPack copied to clipboard

Unexpected InvalidOperationException with .NET 8.0

Open johndaintree opened this issue 2 years ago • 0 comments

I've discovered what I think is a breaking change in .NET 8.0 (and 7) which will affect the use of ILPack. I'm writing it up here in case anyone is already aware of it, and has a workaround/solution/issue logged with Microsoft, before I log something with them.

If I run all the tests in Lokad.ILPack.Tests targetting .NET 7 then the problem reproduces.

A slightly more detail description follows, but in brief....

I'm calling ILPack.AssemblyGenerator with an AssemblyBuilder as the 1st argument.

At various times, ILPack compares SourceAssembly with MethodInfo.DeclaringType.Assembly to determine if the Type is in the assembly being generated.

With .NET 6 this is ok because (for example, with an AssemblyBuilder builder, and a Type "JD"):

builder.GetHashCode() 0x0143a722 builder.GetType("JD").Assembly.GetHashCode() 0x0143a722 SourceAssembly.GetHashCode() 0x0143a722

But... with .NET 8:

builder.GetHashCode() 0x039490e2 builder.GetType("JD").Assembly.GetHashCode() 0x003917f2 SourceAssembly.GetHashCode() 0x039490e2

So in .NET 8 the Assembly for an exported Type is NOT the AssemblyBuilder which is building it.

Does anyone have any insights?

More details below...

I've recently upgraded my application (from which I call AssemblyGenerator.GenerateAssembly) from .NET 6 to .NET 8. and I'm getting the following when generating an assembly (called "jd").

Exception thrown: 'System.InvalidOperationException' in Lokad.ILPack.dll
Referenced assembly cannot be found: jd, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

I've narrowed the error down to Locad.ILPack.Metadata.IsReferencedType which contains:

return type.Assembly != SourceAssembly;

The problem (and the change from .NET 6.0) is that this test is returning a different result when the type.Assembly ought to be the same as SourceAssembly. When my application (and the source of the AssemblyBuilder passed to GenerateAssembly) is .NET 6.0, the assembly jd and SourceAssembly are the same (GetHashCode() returns the same value for each). When the application is .NET 8.0 then the hashcodes are different. As a result, the assembly is deemed to be referenced and not defined. I'm unable to explain how there can be two assemblies (copies I guess).

If I change the test to compare the assembly Fullnames, then everything seems to work as before, but obviously this isn't a good fix.

Does anyone have any suggestions about what's going on?

Thanks.

johndaintree avatar Oct 24 '23 15:10 johndaintree