Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Nota:
Este artículo se aplica a .NET Framework. Para obtener información que se aplica a .NET 5+ (incluido .NET Core), consulte Recursos en archivos .resx.
Dado que los archivos de recursos XML (.resx) deben constar de XML bien definido, incluido un encabezado que debe seguir un esquema específico seguido de datos en pares nombre-valor, es posible que encuentre que crear estos archivos manualmente es propenso a errores. Como alternativa, puede crear archivos .resx mediante programación mediante tipos y miembros de la biblioteca de clases de .NET. También puede usar la biblioteca de clases de .NET para recuperar recursos almacenados en archivos .resx. En este artículo se explica cómo puede usar los tipos y miembros del System.Resources espacio de nombres para trabajar con archivos .resx.
En este artículo se describe cómo trabajar con archivos XML (.resx) que contienen recursos. Para obtener información sobre cómo trabajar con archivos de recursos binarios que se han insertado en ensamblados, vea ResourceManager.
Advertencia
También hay maneras de trabajar con archivos .resx distintos de mediante programación. Al agregar un archivo de recursos a un proyecto de Visual Studio , Visual Studio proporciona una interfaz para crear y mantener un archivo .resx y convierte automáticamente el archivo .resx en un archivo .resources en tiempo de compilación. También puede usar un editor de texto para manipular un archivo .resx directamente. Sin embargo, para evitar dañar el archivo, tenga cuidado de no modificar ninguna información binaria almacenada en el archivo.
Creación de un archivo .resx
Puede usar la System.Resources.ResXResourceWriter clase para crear un archivo .resx mediante programación siguiendo estos pasos:
Cree una instancia de un ResXResourceWriter objeto llamando al ResXResourceWriter(String) método y proporcionando el nombre del archivo .resx. El nombre de archivo debe incluir la extensión .resx. Si crea una instancia del objeto ResXResourceWriter en un bloque
using
, no tiene que llamar explícitamente al método ResXResourceWriter.Close en el paso 3.Llame al ResXResourceWriter.AddResource método para cada recurso que quiera agregar al archivo. Utilice las sobrecargas de este método para agregar datos de cadena, objeto y datos binarios (matriz de bytes). Si el recurso es un objeto , debe ser serializable.
Llame al ResXResourceWriter.Close método para generar el archivo de recursos y liberar todos los recursos. Si el ResXResourceWriter objeto se creó dentro de un
using
bloque, los recursos se escriben en el archivo .resx y los recursos usados por el ResXResourceWriter objeto se liberan al final delusing
bloque.
El archivo .resx resultante tiene el encabezado adecuado y una data
etiqueta para cada recurso agregado por el ResXResourceWriter.AddResource método .
Advertencia
No utilice archivos de recursos para almacenar contraseñas, información relativa a la seguridad o datos privados.
En el ejemplo siguiente se crea un archivo .resx denominado CarResources.resx que almacena seis cadenas, un icono y dos objetos definidos por la aplicación (dos Automobile
objetos). La Automobile
clase, que se define y se instancia en el ejemplo, está etiquetada con el atributo SerializableAttribute.
using System;
using System.Drawing;
using System.Resources;
[Serializable()] public class Automobile
{
private string carMake;
private string carModel;
private int carYear;
private int carDoors;
private int carCylinders;
public Automobile(string make, string model, int year) :
this(make, model, year, 0, 0)
{ }
public Automobile(string make, string model, int year,
int doors, int cylinders)
{
this.carMake = make;
this.carModel = model;
this.carYear = year;
this.carDoors = doors;
this.carCylinders = cylinders;
}
public string Make {
get { return this.carMake; }
}
public string Model {
get {return this.carModel; }
}
public int Year {
get { return this.carYear; }
}
public int Doors {
get { return this.carDoors; }
}
public int Cylinders {
get { return this.carCylinders; }
}
}
public class Example
{
public static void Main()
{
// Instantiate an Automobile object.
Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
// Define a resource file named CarResources.resx.
using (ResXResourceWriter resx = new ResXResourceWriter(@".\CarResources.resx"))
{
resx.AddResource("Title", "Classic American Cars");
resx.AddResource("HeaderString1", "Make");
resx.AddResource("HeaderString2", "Model");
resx.AddResource("HeaderString3", "Year");
resx.AddResource("HeaderString4", "Doors");
resx.AddResource("HeaderString5", "Cylinders");
resx.AddResource("Information", SystemIcons.Information);
resx.AddResource("EarlyAuto1", car1);
resx.AddResource("EarlyAuto2", car2);
}
}
}
Imports System.Drawing
Imports System.Resources
<Serializable()> Public Class Automobile
Private carMake As String
Private carModel As String
Private carYear As Integer
Private carDoors AS Integer
Private carCylinders As Integer
Public Sub New(make As String, model As String, year As Integer)
Me.New(make, model, year, 0, 0)
End Sub
Public Sub New(make As String, model As String, year As Integer,
doors As Integer, cylinders As Integer)
Me.carMake = make
Me.carModel = model
Me.carYear = year
Me.carDoors = doors
Me.carCylinders = cylinders
End Sub
Public ReadOnly Property Make As String
Get
Return Me.carMake
End Get
End Property
Public ReadOnly Property Model As String
Get
Return Me.carModel
End Get
End Property
Public ReadOnly Property Year As Integer
Get
Return Me.carYear
End Get
End Property
Public ReadOnly Property Doors As Integer
Get
Return Me.carDoors
End Get
End Property
Public ReadOnly Property Cylinders As Integer
Get
Return Me.carCylinders
End Get
End Property
End Class
Module Example
Public Sub Main()
' Instantiate an Automobile object.
Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
' Define a resource file named CarResources.resx.
Using resx As New ResXResourceWriter(".\CarResources.resx")
resx.AddResource("Title", "Classic American Cars")
resx.AddResource("HeaderString1", "Make")
resx.AddResource("HeaderString2", "Model")
resx.AddResource("HeaderString3", "Year")
resx.AddResource("HeaderString4", "Doors")
resx.AddResource("HeaderString5", "Cylinders")
resx.AddResource("Information", SystemIcons.Information)
resx.AddResource("EarlyAuto1", car1)
resx.AddResource("EarlyAuto2", car2)
End Using
End Sub
End Module
Sugerencia
También puede usar Visual Studio para crear archivos .resx. En tiempo de compilación, Visual Studio usa el Generador de archivos de recursos (Resgen.exe) para convertir el archivo .resx en un archivo de recursos binarios (.resources) e insertarlo también en un ensamblado de aplicación o en un ensamblado satélite.
No se puede insertar un archivo .resx en un ejecutable en tiempo de ejecución ni compilarlo en un ensamblado satélite. Debe convertir el archivo .resx en un archivo de recursos binarios (.resources) mediante el Generador de archivos de recursos (Resgen.exe). Después, el archivo .resources resultante se puede incrustar en un ensamblado de aplicación o en un ensamblado satélite. Para obtener más información, consulte Creación de archivos de recursos.
Enumerar recursos
En algunos casos, es posible que quiera recuperar todos los recursos, en lugar de un recurso específico, de un archivo .resx. Para ello, puede usar la System.Resources.ResXResourceReader clase , que proporciona un enumerador para todos los recursos del archivo .resx. La System.Resources.ResXResourceReader clase implementa IDictionaryEnumerator, que devuelve un DictionaryEntry objeto que representa un recurso determinado para cada iteración del bucle. Su DictionaryEntry.Key propiedad devuelve la clave del recurso y su DictionaryEntry.Value propiedad devuelve el valor del recurso.
En el ejemplo siguiente se crea un ResXResourceReader objeto para el archivo CarResources.resx creado en el ejemplo anterior y se recorre en iteración el archivo de recursos. Agrega los dos Automobile
objetos definidos en el archivo de recursos a un System.Collections.Generic.List<T> objeto y agrega cinco de las seis cadenas a un SortedList objeto . Los valores del SortedList objeto se convierten en una matriz de parámetros, que se usa para mostrar encabezados de columna en la consola. Los valores de la propiedad Automobile
también se muestran en la consola.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Resources;
public class Example
{
public static void Main()
{
string resxFile = @".\CarResources.resx";
List<Automobile> autos = new List<Automobile>();
SortedList headers = new SortedList();
using (ResXResourceReader resxReader = new ResXResourceReader(resxFile))
{
foreach (DictionaryEntry entry in resxReader) {
if (((string) entry.Key).StartsWith("EarlyAuto"))
autos.Add((Automobile) entry.Value);
else if (((string) entry.Key).StartsWith("Header"))
headers.Add((string) entry.Key, (string) entry.Value);
}
}
string[] headerColumns = new string[headers.Count];
headers.GetValueList().CopyTo(headerColumns, 0);
Console.WriteLine("{0,-8} {1,-10} {2,-4} {3,-5} {4,-9}\n",
headerColumns);
foreach (var auto in autos)
Console.WriteLine("{0,-8} {1,-10} {2,4} {3,5} {4,9}",
auto.Make, auto.Model, auto.Year,
auto.Doors, auto.Cylinders);
}
}
// The example displays the following output:
// Make Model Year Doors Cylinders
//
// Ford Model N 1906 0 4
// Ford Model T 1909 2 4
Imports System.Collections
Imports System.Collections.Generic
Imports System.Resources
Module Example
Public Sub Main()
Dim resxFile As String = ".\CarResources.resx"
Dim autos As New List(Of Automobile)
Dim headers As New SortedList()
Using resxReader As New ResXResourceReader(resxFile)
For Each entry As DictionaryEntry In resxReader
If CType(entry.Key, String).StartsWith("EarlyAuto") Then
autos.Add(CType(entry.Value, Automobile))
Else If CType(entry.Key, String).StartsWith("Header") Then
headers.Add(CType(entry.Key, String), CType(entry.Value, String))
End If
Next
End Using
Dim headerColumns(headers.Count - 1) As String
headers.GetValueList().CopyTo(headerColumns, 0)
Console.WriteLine("{0,-8} {1,-10} {2,-4} {3,-5} {4,-9}",
headerColumns)
Console.WriteLine()
For Each auto In autos
Console.WriteLine("{0,-8} {1,-10} {2,4} {3,5} {4,9}",
auto.Make, auto.Model, auto.Year,
auto.Doors, auto.Cylinders)
Next
End Sub
End Module
' The example displays the following output:
' Make Model Year Doors Cylinders
'
' Ford Model N 1906 0 4
' Ford Model T 1909 2 4
Recuperación de un recurso específico
Además de enumerar los elementos de un archivo .resx, puede recuperar un recurso específico por nombre mediante la System.Resources.ResXResourceSet clase . El ResourceSet.GetString(String) método recupera el valor de un recurso de cadena con nombre. El ResourceSet.GetObject(String) método recupera el valor de un objeto con nombre o datos binarios. El método devuelve un objeto que luego debe ser convertido (en C#) o transformado (en Visual Basic) a un objeto del tipo adecuado.
En el ejemplo siguiente se recupera la cadena de título y el icono de un formulario por sus nombres de recursos. También recupera los objetos definidos por la aplicación usados Automobile
en el ejemplo anterior y los muestra en un DataGridView control .
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;
public class CarDisplayApp : Form
{
private const string resxFile = @".\CarResources.resx";
Automobile[] cars;
public static void Main()
{
CarDisplayApp app = new CarDisplayApp();
Application.Run(app);
}
public CarDisplayApp()
{
// Instantiate controls.
PictureBox pictureBox = new PictureBox();
pictureBox.Location = new Point(10, 10);
this.Controls.Add(pictureBox);
DataGridView grid = new DataGridView();
grid.Location = new Point(10, 60);
this.Controls.Add(grid);
// Get resources from .resx file.
using (ResXResourceSet resxSet = new ResXResourceSet(resxFile))
{
// Retrieve the string resource for the title.
this.Text = resxSet.GetString("Title");
// Retrieve the image.
Icon image = (Icon) resxSet.GetObject("Information", true);
if (image != null)
pictureBox.Image = image.ToBitmap();
// Retrieve Automobile objects.
List<Automobile> carList = new List<Automobile>();
string resName = "EarlyAuto";
Automobile auto;
int ctr = 1;
do {
auto = (Automobile) resxSet.GetObject(resName + ctr.ToString());
ctr++;
if (auto != null)
carList.Add(auto);
} while (auto != null);
cars = carList.ToArray();
grid.DataSource = cars;
}
}
}
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Resources
Imports System.Windows.Forms
Public Class CarDisplayApp : Inherits Form
Private Const resxFile As String = ".\CarResources.resx"
Dim cars() As Automobile
Public Shared Sub Main()
Dim app As New CarDisplayApp()
Application.Run(app)
End Sub
Public Sub New()
' Instantiate controls.
Dim pictureBox As New PictureBox()
pictureBox.Location = New Point(10, 10)
Me.Controls.Add(pictureBox)
Dim grid As New DataGridView()
grid.Location = New Point(10, 60)
Me.Controls.Add(grid)
' Get resources from .resx file.
Using resxSet As New ResXResourceSet(resxFile)
' Retrieve the string resource for the title.
Me.Text = resxSet.GetString("Title")
' Retrieve the image.
Dim image As Icon = CType(resxSet.GetObject("Information", True), Icon)
If image IsNot Nothing Then
pictureBox.Image = image.ToBitmap()
End If
' Retrieve Automobile objects.
Dim carList As New List(Of Automobile)
Dim resName As String = "EarlyAuto"
Dim auto As Automobile
Dim ctr As Integer = 1
Do
auto = CType(resxSet.GetObject(resName + ctr.ToString()), Automobile)
ctr += 1
If auto IsNot Nothing Then carList.Add(auto)
Loop While auto IsNot Nothing
cars = carList.ToArray()
grid.DataSource = cars
End Using
End Sub
End Class
Convertir archivos .resx en archivos .resources binarios
La conversión de archivos .resx en archivos de recursos binarios incrustados (.resources) tiene ventajas significativas. Aunque los archivos .resx son fáciles de leer y mantener durante el desarrollo de aplicaciones, rara vez se incluyen con aplicaciones finalizadas. Si se distribuyen con una aplicación, existen como archivos independientes aparte del ejecutable de la aplicación y sus bibliotecas complementarias. Por el contrario, los archivos .resources se insertan en el ejecutable de la aplicación o en sus ensamblados adjuntos. Además, en las aplicaciones localizadas, al depender de archivos .resx en tiempo de ejecución, la responsabilidad de controlar la reserva de recursos es del desarrollador. En cambio, si se creó un conjunto de ensamblados satélite que contienen archivos .resources insertados, Common Language Runtime administra el proceso de reserva de recursos.
Para convertir un archivo .resx en un archivo .resources , use el Generador de archivos de recursos (resgen.exe), que tiene la siguiente sintaxis básica:
resgen.exe .resxFilename
El resultado es un archivo de recursos binario que tiene el mismo nombre de archivo raíz que el archivo .resx y una extensión de archivo .resources. Después, este archivo se puede compilar en un archivo ejecutable o en una biblioteca en tiempo de compilación. Si usa el compilador de Visual Basic, use la sintaxis siguiente para insertar un archivo .resources en el archivo ejecutable de una aplicación:
vbc filename .vb -resource: .resourcesFilename
Si usa C#, la sintaxis es la siguiente:
csc filename .cs -resource: .resourcesFilename
El archivo .resources también se puede incrustar en un ensamblado satélite mediante Assembly Linker (al.exe), que tiene la siguiente sintaxis básica:
al resourcesFilename -out: assemblyFilename