ResourceLoader in shared assembly - c#

Class Library A
Strings
en-US
Resources.resw
zh-CN
Resources.resw
Application
Views
ViewA.xaml
So I have a View, ViewA that I need to manually load localized strings from. However, whenever I do this, I receive an empty string.
I have tried:
var loader = ResourceLoader.GetForCurrentView();
var myLocalizedText = loader.GetString("Foo");
and
var loader = new ResourceLoader();
var myLocalizedText = loader.GetString("Foo");
The variable myLocalizedText is always an empty string.

I tried to reproduce your issue, however I just got ResourceMap Not Found. exception when using ResourceLoader.GetForCurrentView() or new ResourceLoader().
If we want to construct a resource loader for resources from a library package, we need use ResourceLoader.GetForCurrentView(String) method or ResourceLoader.ResourceLoader(String) constructor. Here the String is the resource identifier of the ResourceMap that the new resource loader uses for unqualified resource references.
Components or library files are typically added into a subfolder of the package they are included in during the build process, similar to their string resources. Their resource identifier usually takes the following form:
ClassLibraryOrAssemblyName/ResourceFileName/StringName
So for your case, we can use following code to load localized strings:
var loader = ResourceLoader.GetForCurrentView("ClassLibraryA/Resources");
var myLocalizedText = loader.GetString("Foo");
For more information, please see: Loading strings from libraries or controls and scenario 6 in Application resources and localization sample.
Besides, please note that for a UWP app, it's better to use GetForCurrentView(String) method:
[ResourceLoader(String) may be altered or unavailable for releases after Windows 8.1. Instead, use GetForCurrentView(String).]
Also if you want to add Chinese language, you'd better use zh-Hans instead of zh-CN:
Include script when there is no suppress script value defined for the language. See the IANA subtag registry for language tag details. For example, use zh-Hant, zh-Hant-TW, or zh-Hans, and not zh-CN or zh-TW.
For more information see: Qualify resources with their language.

Related

How to use the content of a string variable to access an inner resource of a Resources.resx in C#?

In Resources.resx, when accessing a resource in C# visual studio, you do it by : "Properties.Resources." and then a list of resources is avaulable for selection.
I am trying to access resources without knowing the resource name in advanced, its name is revealed on run time only from a content of some string.
Is there any direct way to access the Resources.resx resources names or it can only be done by collecting all resources to a dictionary or some thing like that?
Yes, you can load the resource string manually using code similar to the below:
Assembly resourceAssembly = Assembly.Load("<AppName>.Resources");
ResourceManager resourceManager = new ResourceManager("<AppName>.Resources.<ResourceName>", resourceAssembly);
string resource = resourceManager.GetString("<ResourceName>", culture));

C# Read text file from resources rather than locally [duplicate]

I have a web application project. I generated the DLL and import it in another project. I implemented VirtualPathProvider.
I followed this web site: http://support.microsoft.com/kb/910441/en-us?spid=8940&sid=global, and everything works until I add another site master.
I added site_export.master and changed its Build Action to Embedded Resource.
I changed my page to use the new site master.
GetManifestResourceStream() returns null when I load site_export.master.
I call GetManifestResourceNames() to check if site_export.master exists in the DLL and it does. It's in the list. All of the name spaces match. I didn't list the name space out here.
Why can't GetManifestResourceStream() load my new site_export.master? It loads site.master just fine. I know my DLL is loaded because I can see other files in the DLL.
Remember the following issues...
Step 1. Build action set to embedded resource see
C#’s GetManifestResourceStream Gotcha
Step 2. Use namespace.resourcename see GetManifestResourceStream() returns null ?
Actually, this method returns null if a private resource in another assembly is accessed and the caller does not have ReflectionPermission with the ReflectionPermissionFlag.MemberAccess flag.
Side-hint. To make sure you're in the right assembly and with right name: dump and evaluate all the resources available in your target assembly
string[] names = assembly.GetManifestResourceNames();
(in my case, I misused a namespace from another assembly)
I did this to make it work:
Step 1: Select the resource (CRDF.xsl in my case) and right click > Properties.
Set Build Action to "EmbeddedResource" and Logical Name to name of your choice, e.g. CRDFXSL.
Step 2 : Change your Source code like this:
Assembly _assembly;
_assembly = Assembly.GetExecutingAssembly();
xslStream = _assembly.GetManifestResourceStream("CRDFXSL");
_xmlReader = XmlReader.Create(xslStream);
Thus everything went smoooooooth..
Hint and Caution:
If the "Assembly name" and "Default namespace" does not match in the project file then also GetManifestResourceStream would return null. GetManifestResourceNames still returns the names of assemblies but during loading the manifest would not work.
Try this:
Dim ctx As Windows.ApplicationModel.Resources.Core.ResourceContext = New Windows.ApplicationModel.Resources.Core.ResourceContext()
ctx.Languages = {Globalization.CultureInfo.CurrentUICulture.Name}
Dim rmap As Windows.ApplicationModel.Resources.Core.ResourceMap = Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap
Dim res = rmap.GetValue("Assets/sample.png", ctx)
Dim resFile = Await res.GetValueAsFileAsync
The Windows.ApplicationModel.Resources.Core.ResourceManager.Current.MainResourceMap list all resources.

Access Resources from Externally-Created .resx File

My main Windows Forms (managed C++) project has a class that presents an image with tiles that can be shown or hidden to create a responsive diagram.
I created a separate utility app that helps me get all the images positioned correctly, etc. This app is written in C# and writes a .resx file containing the image data and positioning, using the following code snippet:
using(ResXResourceWriter resx = new ResXResourceWriter(sfd.FileName)) {
resx.AddResource("Size", canvas.Size);
List<int> IDs = canvas.IDs;
resx.AddResource("IDList", IDs);
resx.AddResource("BackgroundIndex", canvas.BackgroundIndex);
foreach(int id in IDs) {
String positionKey = String.Format("Position.id{0}", id);
String visibilityKey = String.Format("Visibility.id{0}", id);
String imageKey = String.Format("Image.id{0}", id);
resx.AddResource(imageKey, canvas.TileImage(id));
resx.AddResource(positionKey, canvas.TilePosition(id));
resx.AddResource(visibilityKey, canvas.TileVisible(id));
}
}
I can open the .resx file in a text editor and see that it is well-formed and contains the expected data.
Then I take that .resx file and add it to my main application's project. Now I can't figure out how to get at the resources inside it. The code I've tried is:
ResourceManager ^ image_rm = gcnew ResourceManager(
"resx_file_name_without_extension", GetType()->Assembly);
ResourceSet ^ image_rs = image_rm->GetResourceSet(
System::Globalization::CultureInfo::CurrentCulture, true, true);
At runtime, the second line (the GetResourceSet call) throws a System.Resources.MissingManifestResourceException with the following message text:
Resource load failure:
Could not find any resources appropriate for the specified culture or the
neutral culture. Make sure "resx_file_name_without_extension.resources" was
correctly embedded or linked into assembly "my_assembly" at compile time, or
that all the satellite assemblies required are loadable and fully signed.
I suspect my problem is...well I don't really know. Maybe I'm not using the right identifier in the ResourceManager constructor. I tried explicitly setting "Excluded From Build: No" and "Content: Yes" in the file's properties, but that had no effect.
Is it even possible to drop an externally-created .resx file into a project and get at the resources within? I definitely need it compiled in; I can't ship a product with dangling .resx files. I can always create a set of static data objects in .cpp files, but the .resx approach seemed more elegant...
Turns out a comment on this unanswered question was the secret sauce. Prepending the root namespace to the identifier made the ResourceManager happy:
ResourceManager ^ image_rm = gcnew ResourceManager(
"my_root_namespace.resx_file_name_without_extension", GetType()->Assembly);
ResourceSet ^ image_rs = image_rm->GetResourceSet(
System::Globalization::CultureInfo::CurrentCulture, true, true);
Just how or why the compiler decided to place the resources within that namespace is still a bit of a mystery to me, but that's trivia for another day.
The question to which I link involves a .resx created with VS within the project, and mine involves adding one created externally, so I think it's a different-enough situation to warrant a separate Q/A.

Resources per version

I know it is possible to store localized versions of resources to be retrieved by the application.
I would like to use a similar principle and to store different versions of data into a resource file/assembly, then use the version as the key to retrieve this data. Is this possible? Is this a common technique?
The data I will be storing is UI Control data identifications.
So for example I would have multiple resources available per version:
Version 1.0 btnID = "thisButton1"
Version 2.0 btnID = "thisButton2"
The application would determine automatically which resource to pick up based on the version currently being used.
You can create a custom class that will wrap the access to the resources and load the correct resource file internally. Assuming you have chosen to name your resource file Resources.1.0.0.0.resources, you can do the following:
public class ResourceReader
{
private static ResourceManager _resourceManager = new ResourceManager(
"Resources." + System.Reflection.Assembly
.GetExecutingAssembly()
.GetName()
.Version.ToString(),
Assembly.GetExecutingAssembly());
// If you have resource property btnID, you can expose it like this:
public static string BtnID
{
get
{
return _resourceManager.GetString("btnID");
}
}
// you can add other properties for every value in the resource file.
}
All you need to do is to know the exact version of your application and to ensure such resource file exists. This can be cumbersome if you have enabled automatic versioning in the assembly info (by using 1.0.* for instance). Of course, you may choose not to use the entire version, but only the major or major and minor version numbers.

Loading ResourceDictionary dynamically

I have a folder in my project, Templates, full of (compiled) XAML ResourceDictionaries.
In a UserControl, I want to load all the templates into the ResourceDictionary. I would use code like the following:
public MyView()
{
InitializeComponent();
foreach (var resourceUri in new GetResourceUrisFromTemplatesFolder())
Resources.MergedDictionaries.Add(
new ResourceDictionary
{ Source = new Uri(resourceUri, UriKind.Relative) });
}
What I need to write is the GetResourceUrisFromTemplatesFolder method. I need it to discover all the resources from that folder.
The URIs could take a form like /MyAssembly;component/MyNS/Templates/Template12345.xaml or ../../Templates/Template12345.xaml
Is this possible?
Do I have to manually convert the names from the assembly's compiled resources (MyAssembly.g.resources)?
BTW, one can also manually load a ResourceDictionary as it seems:
ResourceDictionary dict = new ResourceDictionary();
System.Windows.Application.LoadComponent(dict,
new System.Uri("/SomeAssembly;component/SomeResourceDictionary.xaml",
System.UriKind.Relative));
After that, can talk to that dict object using foreach on the Keys property it has etc
At http://msdn.microsoft.com/en-us/library/ms596995(v=vs.95).aspx says
The XAML file that is loaded can be either an application definition file (App.xaml, for example) >or a page file (MainPage.xaml, for example). The XAML file can be in one of the following locations:
Included in the application package.
Embedded in the application assembly.
Embedded within a library assembly at the site of origin.
Do I have to manually convert the names from the assembly's compiled resources (MyAssembly.g.resources)?
That might be the case and i myself would approach it that way, however the question about how to do just that has been answered already so it should be not that much of an issue. Make sure that the dictionaries' compile action matches, and you probably want to prefix the names with a pack uri.

Categories

Resources