Alex 75
Alex 75

Reputation: 3266

.net - Get embedded resource path from Assembly

I've a .net6 F# solution with a test project.
The test project is in a folder named "MyProject.Core.Tests" and the project file is Core.UnitTests.fsproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6</TargetFramework>
    <AssemblyName>UnitTests.Core</AssemblyName>
    <!--DefaultNamespace>UnitTests.Core</DefaultNamespace-->
  </PropertyGroup>
  <ItemGroup>
    <EmbeddedResource Include="aaa.txt"  />

In the solution the F# project is shown as "Core.UnitTests". This is the MySolution.sln entry:

Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "Core.UnitTests", "MyProject.Core.Tests\Core.UnitTests.fsproj", "{027C4CE5-B47B-4E4E-B7D2-477B4AB981F2}"
EndProject

In the project I have a file "aaa.txt" with BuildAction "Embedded Resource".

I try to read it with

module MyModule
  
  let assembly = Assembly.GetExecutingAssembly()
  let assemblyName = assembly.GetName().Name
  let stream = assembly.GetManifestResourceStream($"{assemblyName}.aaa.txt")

But stream is null.
If I print out "assemblyName" it is: "UnitTests.Core".
If I get all the resources within the Assembly using assembly.GetManifestResourceNames() I get "Core.UnitTests.aaa.txt" instead.

Why the resource is stored in "Core.UnitTests.aaa.txt" if the Assembly name is "UnitTests.Core" ?

It seems that the embedded resource path is generated using the project file name.
I also tried to set the DefaultNamespace in the project file but nothing changed.
How can I get the initial part of the resources from the Assembly?

[EDIT]

I found this workaround:

module MyModule
  
  let nspace = assembly.GetExportedTypes().[0].Namespace
  let stream = assembly.GetManifestResourceStream($"{nspace}.aaa.txt")

Not sure how to get the default namespace in a more clean way from F# module (that code is not in a type/class).

Upvotes: 2

Views: 297

Answers (1)

Brian Berns
Brian Berns

Reputation: 17153

I think the resource name is qualified by the project's RootNamespace, rather than its DefaultNamespace, so this seems to work in the .fsproj file:

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>UnitTests.Core</RootNamespace>
  </PropertyGroup>

This is implemented by the CreateFSharpManifestResourceName build task.

Upvotes: 3

Related Questions