Skip to content

Conversation

@zhuman
Copy link

@zhuman zhuman commented Dec 19, 2025

Thanks so much for the existing work on this project, it's awesome to get source generator support for ResX files instead of the old crusty VS custom tool!

This PR adds support for several missing features that the old VS custom tool had which are blockers for using this source generator with all the traditional use cases for GUI apps.

  • Support for resources of arbitrary types - Previously this project could only generate code for reading strings, but the traditional set of WinForms and WPF uses cases allow for images, files, icons, etc. to be loaded and cast automatically to the appropriate resource type. ResourceManager has a system of handlers to get support to cast to/from various types like System.Drawing.Icon, and these are specified in the resx file. Other frameworks could also register type converters with ResourceManager so having support for totally arbitrary types should solve any potential use case.
  • Support for LogicalName and ManifestResourceName metadata - MSBuild <EmbeddedResource> items can have LogicalName or ManifestResourceName specified, which affects the internal resource stream name.

There was a big blocker in order to accomplish this, which is that we have to parse .NET fully qualified type names from the ResX file without loading the types themselves (since source analyzers use netstandard2.0 which can't depend on WinForms or other frameworks). Weirdly, the .NET BCL doesn't expose its internal type name parser outside of the type loader! So I had to write a parser from scratch using the grammar specified on MSDN: https://learn.microsoft.com/en-us/dotnet/fundamentals/reflection/specifying-fully-qualified-type-names.

I did add a dependency on a Nuget package called sly which implements a lexer and parser framework I used for parsing type names. This library is also licensed under the MIT license so is compatible with using in this project. I added significant unit testing of the parser so I'm confident it handles just about any resource type anyone could come up with. I can appreciate if fully parsing the type name seems like overkill, but after trying a few simpler approaches and running into issues with common ResX files (some types are fully qualified with the assembly, others aren't, etc.), I figured it would be the only foolproof approach.

Beyond the type name parser, I've added several new test cases to validate that non-string types work properly and LogicalName is respected. I added 3 new diagnostic messages to cover cases where the ResX type is invalid or unsupported.

This would resolve #2 and #10

* Wrote a full .NET fully qualified type name parser using a recursive descent parser
* Added support for System.Resources.ResXFileRef resources, which require extra parsing to generate the right code
…to the 2.0 format, fix TypeNameParser to handle assembly names with dots and dashes, add ToCSharp method on ParsedTypeName
…ata on EmbeddedResource items used by the resource compiler to general the internal file name. Without this, we break with any ResX with these values explicitly specified.

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net8.0-windows</TargetFramework>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could keep TargetFramework as net8.0 and split the tests into two projects: net8.0 and net8.0-windows. That would let the net8.0 tests run in CI.

@@ -1,107 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation was changed from tabs to spaces. Can you please revert this to make the review easier?

<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" />
<PackageReference Include="sly" Version="3.7.7" PrivateAssets="all" GeneratePathProperty="true" IncludeInPackage="true" />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d prefer to avoid third-party dependencies where possible. Are there alternatives to using sly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for System.Drawing.Bitmap and System.Byte[]

2 participants