We use CQRS in our applications and decided to place the handlers together with their requests and validators in the same file. Our resources are "grouped" per request using <EmbeddedResource Include="Request.resx" DependentUpon="Request.cs"/>.
However just moving one class from one source file to another, this caused an unexpected bug in our application by which certain resources could no longer be found. It turned out the resources got a different name in some cases.
Steps to Reproduce
Have the following resource files (contents don't matter):
public sealed class RequestClass { }
public sealed class RequestClassValidator { }
RequestRecord.cs:
public sealed record RequestRecord();
public sealed class RequestRecordValidator { }
Build the project (dotnet build) and open de binary in a decompiler like JetBrains dotPeek and open the listing of the resource files.
Expected Behavior
Listed resource files:
MyProject.RequestClass.resources
MyProject.RequestRecord.resources
Actual Behavior
Listed resource files:
MyProject.RequestClass.resources
MyProject.RequestRecordValidator.resources
Analysis
The task CreateCSharpManifestResourceName parses a part of the source code in the source file to extract the class name. When it fails to do so, it falls back to the file name of the source class.
Previously it worked fine by accident: It didn't recognize any class (because it didn't parse records) and fell back to the file name. However, now we've moved the related classes together in the same file it found the first class in the file (RequestRecordValidator) and decided that should be the manifest resource name.
Workarounds
Manually set the ManifestResourceName property
If you change public sealed record RequestRecord to public sealed record class RequestRecord it works as expected
Team triage: Thank you for the filing the bug and for the great analysis!
This issue currently doesn't meet bar for fixing, but we are leaving this open for upvotes.
Issue Description
We use CQRS in our applications and decided to place the handlers together with their requests and validators in the same file. Our resources are "grouped" per request using
<EmbeddedResource Include="Request.resx" DependentUpon="Request.cs"/>
.However just moving one class from one source file to another, this caused an unexpected bug in our application by which certain resources could no longer be found. It turned out the resources got a different name in some cases.
Steps to Reproduce
Have the following resource files (contents don't matter):
Project file
MyProject.csproj
:RequestClass.cs:
RequestRecord.cs:
Build the project (
dotnet build
) and open de binary in a decompiler like JetBrains dotPeek and open the listing of the resource files.Expected Behavior
Listed resource files:
Actual Behavior
Listed resource files:
Analysis
The task
CreateCSharpManifestResourceName
parses a part of the source code in the source file to extract the class name. When it fails to do so, it falls back to the file name of the source class.https://github.com/dotnet/msbuild/blob/227092b45a18b5892638d87fe4bc1b07ac4f8d96/src/Tasks/CreateCSharpManifestResourceName.cs#L112-L134
Previously it worked fine by accident: It didn't recognize any class (because it didn't parse records) and fell back to the file name. However, now we've moved the related classes together in the same file it found the first class in the file (
RequestRecordValidator
) and decided that should be the manifest resource name.Workarounds
public sealed record RequestRecord
topublic sealed record class RequestRecord
it works as expectedVersions & Configurations
No response