0

I got an assembly containing only static classes with constants

public static class C {
    public const int Value = 123;
}

I use this assembly in different applications and it is marked with CopyLocal = false and is not deployed.

This work for netframework applications but for netcoreapp I get an error message saying the assembly can not be found.

The assembly is not referenced in the compiled code (verified with ildasm) but there is still a reference in the .deps.json file.

Do I need to deploy the assembly with core applications or is there a settings to exclude it from the .deps.json file?

(Most of my netframework applications are only small executables so it seemed unnecessary to include a multi-megabyte, not used, assembly in the deploy. Core application are large and multi-file from start so it doesn't matter)

Edit: found the problem. The assembly didn't actually have CopyLocal = false. It used a .targets file to remove it at build time

<Target Name="PreventConstantsCopyLocal" AfterTargets="ResolveReferences">
    <ItemGroup>
        <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" 
                                 Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'MyConstants'" />
    </ItemGroup>
</Target>

I just added a an extra condition

And ('%(MSBuildRuntimeType)' == '' Or '%(MSBuildRuntimeType)' == 'Full')

so the constants are copied to output in core builds.

adrianm
  • 14,468
  • 5
  • 55
  • 102

1 Answers1

0

Disclaimer As a general rule you should always use CopyLocal=True, if the reference is not contained within the GAC (Global Assembly Cache).

The Problem: When you use an assembly, with CopyLocal = false set, it means that the Assembly (.dll file) will not be placed into the output directory of whatever you just built.

What happens next is the following: As soon as the missing assembly is used somewhere in your executing code, the runtime environment will try to load it. for .Net Framework, this happens in a very specific way.

This is different as dotnetcore do. They have no GAC, but there is something called the Runtime package Store

The Solution:

Maybe Is there any GAC equivalent for .NET Core?

  • The issue here is the assembly is not used anywhere in the executing code. The assembly only contain constants which are compiled directly into the code. `In fact, when the compiler encounters a constant identifier in C# source code [...] it substitutes the literal value directly into the intermediate language (IL) code that it produces.` https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constants – adrianm Mar 16 '20 at 06:49
  • i tried to reproduce your situation by creating two assemblies, one assembly (test) with one public constant, 2nd assembly (consumer) referencing the first assembly, copylocal false, and using the constant. when i publish it, the test.dll is not even mentioned in deps.json (and not in the publish directory). i moved that to a machine running dotnetcore and it worked. so i cannot reproduce your problem. i was using dotnetcore 3.1. sorry, im out. you could maybe try turnin on the "readytorun" option, available from .netcore 3.0, which does some ahead of time compiling for you? – Michael Schönbauer Mar 16 '20 at 22:02
  • thanks. Your comment got me on the right track and I found the problem, see my update – adrianm Mar 17 '20 at 08:22