Embedded resources in assembly containing culture

2019-04-08 05:28发布

问题:

I'm trying to embed some email templates in a class library. This works fine, until I use a filename containing a culture-name with the following notation: templatename.nl-NL.cshtml The resource does not seem to be available.

Example code:

namespace ManifestResources
 {
    class Program
    {
        static void Main(string[] args)
        {
            var assembly = Assembly.GetExecutingAssembly();

            // Works fine
            var mailTemplate = assembly.GetManifestResourceStream("ManifestResources.mailtemplate.cshtml");

            // Not ok, localized mail template is null
            var localizedMailTemplate = assembly.GetManifestResourceStream("ManifestResources.mailtemplate.nl-NL.cshtml");
        }
    }
}

Templates both have build action set to 'EmbeddedResource'.

Obvious solution is to use a different notation, but I like this notation. Anyone has a solution for this problem?

回答1:

I hope I am not late with answer.

When you add templatename.nl-NL.cshtml as embedded resource, it lands in satellite assembly with resources for nl-NL language.

If you go to bin/debug directory, you'll find nl-NL folder with NAMESPACE.resources.dll in it.

If you decompile this assembly, you'll find templatename.cshtml file inside.

To read it, you have to get this assembly and read resource from it.

To get it, you have to execute this code:

var mainAssembly = AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "ConsoleApp2");

ConsoleApp2 was namespace where I had all my resources. Code above will get assembly only if it is already loaded. I assumed it is.

Then you have to get satellite assembly. This is main difference between standard file reading from embedded resource:

var satelliteAssembly = mainAssembly.GetSatelliteAssembly(CultureInfo.CreateSpecificCulture("nl-NL"));

And then we have standard method to read resource file:

var resourceName = "ConsoleApp2.templatename.cshtml";

using (Stream stream = satelliteAssembly.GetManifestResourceStream(resourceName))
    using (StreamReader reader = new StreamReader(stream))
    {
        string result = reader.ReadToEnd(); // nl-NL template
    }

Example project file here.



回答2:

Are you sure you have the right name for the ResourceSet when you open the ResourceStream? Unless ManifestResources is your project base namespace and the .cshtml file lives in the root folder that resourceset name is probably invalid.

The way .NET projects generate resourceSet name you use to open the resource stream is based on base namespace plus the folder hierarchy. For Example:

baseNamespaceOfProject.Views.Controller.YourPage.nl-NL.cshtml

The easiest way to check make sure you can see what the resource looks like is to open the final assembly (or resource assembly) with a tool like Reflector/DotPeek and see what the actual embedded resourceSet and Resource Ids are.