dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.06k forks source link

Changed behavior of DependencyContext.Default.RuntimeLibraries? #34288

Open dominikjeske opened 1 year ago

dominikjeske commented 1 year ago

After recent updated of SDK/Runtime our ASP.NET Core 6 app (runtime 6.0.14 and SDK 7.0.201) break because DependencyContext.Default.RuntimeLibraries started to return duplicated entries. After investigation we find out that duplicated entry has different type of 'Reference assembly'. Fix was simple but I'm wonder is this intended behavior or maybe bug?

dotnet-issue-labeler[bot] commented 1 year ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-dependencymodel See info in area-owners.md if you want to be subscribed.

Issue Details
After recent updated of SDK/Runtime our ASP.NET Core 6 app (runtime 6.0.14 and SDK 7.0.201) break because DependencyContext.Default.RuntimeLibraries started to return duplicated entries. After investigation we find out that duplicated entry has different type of 'Reference assembly'. Fix was simple but I'm wonder is this intended behavior or maybe bug?
Author: dominikjeske
Assignees: -
Labels: `area-DependencyModel`, `untriaged`
Milestone: -
ViktorHofer commented 1 year ago

@dominikjeske do you have a repro or can share the deps.json content before and after? Thanks

mkeeton commented 1 year ago

After recent updated of SDK/Runtime our ASP.NET Core 6 app (runtime 6.0.14 and SDK 7.0.201) break because DependencyContext.Default.RuntimeLibraries started to return duplicated entries. After investigation we find out that duplicated entry has different type of 'Reference assembly'. Fix was simple but I'm wonder is this intended behavior or maybe bug?

What was the "simple fix" you applied. We've suddenly got the same problem popping up on 2 out of 10 dev machines.

joseoliveira-silva commented 1 year ago

After recent updated of SDK/Runtime our ASP.NET Core 6 app (runtime 6.0.14 and SDK 7.0.201) break because DependencyContext.Default.RuntimeLibraries started to return duplicated entries. After investigation we find out that duplicated entry has different type of 'Reference assembly'. Fix was simple but I'm wonder is this intended behavior or maybe bug?

What was the "simple fix" you applied. We've suddenly got the same problem popping up on 2 out of 10 dev machines.

A quick mitigation is to downgrade the .NET SDK version to 6.

dominikjeske commented 1 year ago

After recent updated of SDK/Runtime our ASP.NET Core 6 app (runtime 6.0.14 and SDK 7.0.201) break because DependencyContext.Default.RuntimeLibraries started to return duplicated entries. After investigation we find out that duplicated entry has different type of 'Reference assembly'. Fix was simple but I'm wonder is this intended behavior or maybe bug?

What was the "simple fix" you applied. We've suddenly got the same problem popping up on 2 out of 10 dev machines.

We just added simple Where in our code - it works in our scenario

DependencyContext.Default.RuntimeLibraries .Where(l => l.Type != "reference")

ghost commented 1 year ago

This issue has been marked needs-author-action and may be missing some important information.

ghost commented 1 year ago

This issue has been automatically marked no-recent-activity because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will remove no-recent-activity.

jane-u commented 1 year ago

Will be nice to understand, is this a bug/side effect or feature.

ericstj commented 1 year ago

We need a repro of this. I don't see a deps.json attached to this bug and the description above is not sufficient to repro. I tried as suggested and the problem did not reproduce. Here's a sample project I tried: https://github.com/ericstj/sample-code/tree/depcontext-test

Output on net7.0 was:

Runtime libraries: 8
Duplicates: 0
Type project: 2
Type package: 6

Similar on 6.0 (count was 11) and 8.0 (same count).

Can someone with a repro project share their project or modify the repro I shared above to reproduce the issue? Otherwise we might need to resolve as no-repro.

ghost commented 1 year ago

This issue has been marked needs-author-action and may be missing some important information.

dominikjeske commented 1 year ago

@ericstj I have tested your solution and was very confused because everything was ok. I have done some investigation and finally found how it can be reproduced. In our solutions we are using AssemblyName attribute in projects. You can set this in your lib.csproj

<AssemblyName>Test</AssemblyName>

and in main program execute this

var count = DependencyContext.Default.RuntimeLibraries.Where(l => l.Type == "reference").Count();

it should return one element on actual SDK. When you introduce global.json and set SDK used to build you will see that on SDK below 7.0.2* (for example 7.0.109) you will get zero elements and every SDK after will give you additional reference assembly.

jane-u commented 1 year ago

I don't have a repro at the moment, but I have the example of change I had to make in code that uses Scrutor:

public static IImplementationTypeSelector FromThisSolution(this ITypeSourceSelector selector)
{
    return selector
        .FromApplicationDependencies(assembly => 
            assembly.FullName.StartsWith("SomeName"));
}

public static IImplementationTypeSelector FromThisSolution(this ITypeSourceSelector selector)
{
    return selector.FromAssemblies(
        DependencyContext.Default.RuntimeLibraries
            .Where(library => library.Type != "reference")
            .SelectMany(lib => lib
                .GetDefaultAssemblyNames(DependencyContext.Default)
                .Where(assembly => assembly.FullName.StartsWith("SomeName"))
                .Select(Assembly.Load)));
}

With Throw strategy it throws on duplicate, using the first version of FromThisSolution:

        services.Scan(scan => scan
            .FromThisSolution()
            .AddClasses(c => c.AssignableTo(typeof(ISomeInterface)), false)
            .UsingRegistrationStrategy(RegistrationStrategy.Throw)
            .AsImplementedInterfaces()
            .WithSingletonLifetime());
ericstj commented 1 year ago

Thank you @dominikjeske that did it. This is adding an additional entry to the deps.json as follows:

      "test/1.0.0": {
        "runtime": {
          "test.dll": {}
        }
      },
      "test.Reference/1.0.0.0": {
        "runtime": {
          "test.dll": {
            "assemblyVersion": "1.0.0.0",
            "fileVersion": "1.0.0.0"
          }
        }
      }

Two different libraries are listed in the deps file as well:

    "test/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    },
    "test.Reference/1.0.0.0": {
      "type": "reference",
      "serviceable": false,
      "sha512": ""
    }

This seems to be a creation of the SDK's GenerateDepsFile task. Nowhere else does this appear - not in the project.assets.json or the build log.

Seems like this was regressed with https://github.com/dotnet/sdk/pull/28963. That change did include a flag to skip the new behavior: IncludeProjectsNotInAssetsFileInDepsFile. I was able to set this and the problem goes away.

<IncludeProjectsNotInAssetsFileInDepsFile>false</IncludeProjectsNotInAssetsFileInDepsFile>

Still it seems a bug that the SDK treats this as a runtime assembly at all. Something got confused with this mapping. I suspect somewhere there is a bad assumption about project-name == assembly name or similar. Transferring this to SDK. I updated the sample repo so that it reproduces the behavior: https://github.com/ericstj/sample-code/tree/depcontext-test

dominikjeske commented 1 year ago

@ericstj Thanks a lot for investigation. For me it also looks like a bug.