How to Create and Use Resources in .Net

How to create and use resources in .NET

Well, after searching around and cobbling together various points from around StackOverflow (gee, I love this place already), most of the problems were already past this stage. I did manage to work out an answer to my problem though.

How to create a resource:

In my case, I want to create an icon. It's a similar process, no matter what type of data you want to add as a resource though.

  • Right click the project you want to add a resource to. Do this in the Solution Explorer. Select the "Properties" option from the list.
  • Click the "Resources" tab.
  • The first button along the top of the bar will let you select the type of resource you want to add. It should start on string. We want to add an icon, so click on it and select "Icons" from the list of options.
  • Next, move to the second button, "Add Resource". You can either add a new resource, or if you already have an icon already made, you can add that too. Follow the prompts for whichever option you choose.
  • At this point, you can double click the newly added resource to edit it. Note, resources also show up in the Solution Explorer, and double clicking there is just as effective.

How to use a resource:

Great, so we have our new resource and we're itching to have those lovely changing icons... How do we do that? Well, lucky us, C# makes this exceedingly easy.

There is a static class called Properties.Resources that gives you access to all your resources, so my code ended up being as simple as:

paused = !paused;
if (paused)
notifyIcon.Icon = Properties.Resources.RedIcon;
else
notifyIcon.Icon = Properties.Resources.GreenIcon;

Done! Finished! Everything is simple when you know how, isn't it?

How to implement resource files localization ASP-NET.core?

The default localization setup of .net core can be based on one shared resource file or based on the class name.

In your case, you can use the shared resource approach, but you have to create the cutomized localizer in each controller/class by providing the factory with the desired resource type.

First create a class library with the desired resources, create a public dummy class for each resource type you want, so the class library structure can be like below:

// SharedResourcesLibrary.csproj

- UsersResources.cs
- UsersResources.fr-ca.resx
- UsersResources.en-ca.resx

- ContentResources.cs
- ContentResources.fr-ca.resx
- ContentResources.en-ca.resx

...

The dummy classes are empty, they are used just as a type to call the relevant resx file.

// Dummy users resources class
public class UsersResources { }

Then after referencing the ResourcesLibrary project into other projects, you can use the resources by calling the relevant resource type (the dummy class).:

using SharedResourcesLibrary;

public class UsersController : Controller
{
private readonly IStringLocalizer _localizer;

public UsersController(IStringLocalizerFactory factory)
{
var type = typeof(UsersResources);
_localizer = factory.Create(type);
}

public IActionResult About()
{
ViewData["Message"] = _localizer["Welcome."];
}
}

To use other resources just create the localizer using the relevant resource type.


Another approach can be done by creating custom multiple IStringLocalizers according to your areas, then inject them in the controllers.

// Create one localizer for each area
public class UsersLocalizer : IStringLocalizer
{
private readonly IStringLocalizer _localizer;

public UsersLocalizer(IStringLocalizerFactory factory)
{
var type = typeof(UsersResources);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create(type);
}

public LocalizedString this[string name] => _localizer[name];

public LocalizedString this[string name, params object[] arguments] => _localizer[name, arguments];

// ...
}

Similarly you can create localizers for other areas... then register in startup:

services.AddTransient<IStringLocalizer, UsersLocalizer>();
services.AddTransient<IStringLocalizer, AdminsLocalizer>();
services.AddTransient<IStringLocalizer, ContentLocalizer>();
// ...

This way all localizers will be registered, and if you simply inject IStringLocalizer it will get the last registered one, because all localizers are implementing the same IStringLocalizer interface.

So you have to do type selection for injecting the correct localizer:

public UsersController : Controller
{
private readonly IStringLocalizer _localizer;

public UsersController(IEnumerable<IStringLocalizer> localizers)
{
_localizer = localizers.FirstOrDefault(x => x.GetType() == typeof(UsersLocalizer));
}

public IActionResult About()
{
ViewData["Message"] = _localizer["Welcome."];
}
}

You can refere to this article for different ways of Registering multiple implementation with the same interface in Asp.Net Core

how to use resources manually in C#(no IDE act)?

well finally i found the answer of my question .
i really didn't get the correct and the best answer from searching the internet and asking questions .

its all about resources , everything from outside used in a projection must go through these steps :

  1. imported/downloaded to project folder.

(it's really common to put the files to a Resource folder as a projection sub-folder)


  1. defined/submitted/converted to a local or global projection's .resx file.

(.resx file is a XML)


  1. get a handle from C#.net to be accessible .

(from .resx designer file)

(this is done by defining - usually as a property - in the global or local C#.net .resx designer)

if we assume local .resx as a personal backpack for classes and projection(global) .resx file as a public drawer , every classes provide their resources from their own backpack and the public drawer . by conventional direct procedure of providing resources , Visual Studio IDE don't let the classes use other classes resources . but if you go a little further into .resx files and the designer files this would be possible .

first let me explain how a class can use other classes resources .

when you import files into a local .resx a hard encoded copy of the files imported into the XML of the .resx. you can access XML of the local .resx file if you open the .resx file with a XML-editor .

for example if you imported an icon file into a form
you will see these codes in the XML related to the icon :

(to access the XML-editor in VS just easily right-click the .resx file and click open with then choose XML-editor)

<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing"
mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAkAMDAAAAEACACoDgAAlgAAACAgAAABAAgAqAgAAEAPAAAYGAAAAQAIAMgGAAD
oFwAAEBAAAAEACABoBQAAsB4AAAAAAAABACAA510BABgkAAAwMAAAAQAgAKglAAAAggEAICAA
AAEAIACoEAAAqKcBABgYAAABACAAiAkAAFC4AQAQEAAAAQAgAGgEAADYwQEAKAAAADAAAABgAAA
AAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAZHBQAHR4ZABgkFAAaKRYAHyAaAB0rGQ
AeMBkAIiQcACQpHgAiNBwAJDkeACUn
.
.
.
+Pn5D/j5+Q/4+fkP+Pn5D/j5+Q/4+fkP+Pn5D/j5+Q/4+fk
P+Pn5D/j5+Q/4+fkPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA4AMAAAABA
AAAAAAAAAEAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAA
</value>
</data>

the file encoded , you can see VS gives it a name ($this.Icon) and specify its type and mimetype there . so these property's now is changeable

for accessing resources in designer or constructor files an object of System.Resources.ResourceManager must be created .
the constructor of ResourceManager has two overload , one of them just use resourceSource type as the input parameter . it has to be the resource type of the host of resources . one can get it like this :

typeof(Form1) ;

so creating a ResourceManager object :

System.Resources.ResourceManager resource = new System.Resources.ResourceManager(typeof(Form1))

the object resource now has a GetObject() method to access .resx imported files by their name , for example for the icon :

((System.Drawing.Icon)(resources.GetObject("$this.Icon")))

if you open the designer file of the form you can see the codes for the icon of the form :

this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));

resource is a ResourceManager object created in the base form class by the IDE so you can use it here in the designer file easily .

if you want to use for example the icon of form1 in form2 you can refer to it like this :

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
**this.Icon = (System.Drawing.Icon)((new System.Resources.ResourceManager(typeof(Form1))).GetObject("$this.Icon"));***
this.Name = "Form2";
this.Text = "Form2";
this.ResumeLayout(false);

(look carefully the line started with **)

maybe its better to defined it as a public static property in the form constructor to avoid too much typing of nestings :

public static System.Drawing.Icon icon
{
get
{
return (System.Drawing.Icon)((new System.Resources.ResourceManager(typeof(Form1))).GetObject("$this.Icon"));
}
}

so in the form2 designer :

this.Icon = Form1.icon ;

so far using resources of other classes revealed now lets talk about defining and using global projections resources manually !

there's no hard-copy of the imported files in a global .resx file . there's just a reference to it .

for example you imported icon with the IDE , it creates a Resource sub-folder and put the file in it .
now if you open properties in the solution manager and open the Resource.resx with a XML editor (Right-Click > Open With > XML editor) you can see this code :

<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="PerfCenterCpl" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>

you can see above in the value it specified its reference address and its type and even its type version ! and its culture type and really interesting it has a key !

from its address , it seems files just added to projection for integrity . global resources can be every where in the projection folder , in the computer , in the network or in the internet !

it has a unique key ! seems we can access resources by their key in the project too !

now its time for resource to gets its handle
if you open Resource.resx in the solution manager and open the Resource Designer you can see it gets its handle by a property :

       internal static System.Drawing.Icon icon {
get {
object obj = ResourceManager.GetObject("icon", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}

so the resource is accessible with Properties.Resources.icon
and doesnt need any type casting :

this.Icon = Properties.Resources.icon ;

now if further processes on the resources needed , global resources can be a method accepting input parameters !

in my problem i give the resource a handle but there isn't any resource reference in the XML

How do I create a Resources file for a Console Application?

The project template for a console mode application doesn't have pre-cooked Resources. You simply add it with Project + Properties, Resources tab, click the "Click here to create one" link. Take an hour and click around some more. This is all very discoverable but you have to take a look.

asp.net core with resource file (resx)

I found another approach that worked good for my problem.

http://codeopinion.com/asp-net-core-embedded-resource/

Just need to create a folder on project (Resources in my case), and then, in project.json, I included the following code:

"buildOptions": {
"embed": ["Resources/**/*"]
}

and then, my code:

var assembly = Assembly.GetExecutingAssembly();
var logoStream = assembly.GetManifestResourceStream("ProjectNamespace.Resources.logo.png");


Related Topics



Leave a reply



Submit