In a C# project, the generated resource name for an Embedded Resource
by default undergoes some mangling to make the resulting name a namespaced valid language identifier.
For example Foo/Bar/123.txt
becomes {Default Namespace}.Foo.Bar._123.txt
and I have to load it with asm.GetManifestResourceStream("Yuck.Foo.Bar._123.txt")
.
I would much rather have my resources retain their relative path such as Foo/Bar/123.txt
to better simulate a virtual file system and so I can load them such as asm.GetManifestResourceStream("Foo/Bar/123.txt")
.
Now I know that .Net does not place restrictions on resource names, so it seems feasible.
But how do I get the build engine to generate sensible path names for me?
In the .csproj
file, the Embedded Resources
are defined as <EmbeddedResource>
items.
These have metadata named <LogicalName>
which allows overwriting the name of the resource from whatever would otherwise be generated.
For example:
<ItemGroup>
<EmbeddedResource Include="Foo\Bar\123.txt">
<LogicalName>Foo\Bar\123.txt</LogicalName>
</EmbeddedResource>
</ItemGroup>
would generate a resource which could be loaded using asm.GetManifestResourceStream("Foo\Bar\123.txt")
To do this for all of our embedded resources, we can add a renaming task to the .csproj file which runs before the default names are generated and explicitly assigns names of our choosing:
<Target Name="ModifyEmbeddedResourceNames" BeforeTargets="CreateManifestResourceNames">
<ItemGroup>
<EmbeddedResource>
<LogicalName>%(EmbeddedResource.Identity)</LogicalName>
</EmbeddedResource>
</ItemGroup>
</Target>
With this we get resources named by their Identity
.