Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: Meta en 9 Marzo 2024, 22:53 pm



Título: Mejor guardado para XML
Publicado por: Meta en 9 Marzo 2024, 22:53 pm
Tengo este código para guardar y recuperar datos en XML.

Siempre me dicen que use getters y setters.

La forma que me enseñaron es antigua y nada que ver con ahora.

Por ejemplo.
Código
  1. using System.Xml;
  2.  
  3. namespace Guardar_y_cargar_datos_en_archivo.xml_.NET_7._0
  4. {
  5.    public partial class Form1 : Form
  6.    {
  7.        public Form1()
  8.        {
  9.            InitializeComponent();
  10.        }
  11.  
  12.        // Guarda los datos introducidos a parte de crear el archivo "miXML.xml".
  13.        private void button_Guardar_Click(object sender, EventArgs e)
  14.        {
  15.            XmlWriter w = XmlWriter.Create(@"archivo.xml");
  16.            w.WriteStartElement("MiInfo");
  17.            w.WriteElementString("TextBox", textBox1.Text);
  18.            w.WriteElementString("CheckBox", checkBox1.Checked.ToString());
  19.            w.WriteElementString("radioButton1_Luz_ON", radioButton1.Checked.ToString());
  20.            w.WriteElementString("radioButton2_Luz_OFF", radioButton2.Checked.ToString());
  21.            w.WriteEndElement();
  22.            w.Close();
  23.        }
  24.  
  25.        private void Form1_Load(object sender, EventArgs e)
  26.        {
  27.            try
  28.            {
  29.                XmlReader r = XmlReader.Create("archivo.xml");
  30.                r.ReadStartElement("MiInfo");
  31.                textBox1.Text = r.ReadElementContentAsString();
  32.                checkBox1.Checked = Convert.ToBoolean(r.ReadElementContentAsString());
  33.                radioButton1.Checked = Convert.ToBoolean(r.ReadElementContentAsString());
  34.                radioButton2.Checked = Convert.ToBoolean(r.ReadElementContentAsString());
  35.                r.ReadEndElement();
  36.                r.Close();
  37.            }
  38.            catch (Exception)
  39.            {
  40.  
  41.                //
  42.            }
  43.        }
  44.    }
  45. }

Por supuesto, me funciona como me han enseñado.
El archivo es este que se queda guardado.

Código
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <MiInfo>
  3. <TextBox>Hola amigo.</TextBox>
  4. <CheckBox>True</CheckBox>
  5. <radioButton1_Luz_ON>False</radioButton1_Luz_ON>
  6. <radioButton2_Luz_OFF>True</radioButton2_Luz_OFF>
  7. </MiInfo>

Entonces.

¿Cuál es la mejor manera de programarlo?

Saludos.


Título: Re: Mejor guardado para XML
Publicado por: **Aincrad** en 9 Marzo 2024, 23:24 pm
Por que no usar json ? si quieres modernizarte, puedes usar : SettingsProvider.net (https://github.com/JakeGinnivan/SettingsProvider.net) es el que uso en todas mis apps , es realmente bueno.

Si todavía quieres usar XML, puedes buscar algún snippet aquí :  https://foro.elhacker.net/net/indice_de_la_libreria_de_snippets_para_vbnet-t485444.0.html (https://foro.elhacker.net/net/indice_de_la_libreria_de_snippets_para_vbnet-t485444.0.html) y puedes convertir de VB a C# usando : https://converter.telerik.com (https://converter.telerik.com)


Título: Re: Mejor guardado para XML
Publicado por: Eleкtro en 10 Marzo 2024, 02:52 am
La consulta que realizas se puede interpretar de varias formas. ¿Cual es exactamente el aspecto que buscas mejorar de ese código?. Utilizar directamente el método getter/setter de una o varias propiedades para controlar de forma eventual el cómo y el cuando guardar cierta configuración del usuario, eso podría no suponer mejor estructuración del código, ni tampoco mejora alguna con respecto a la utilización de la clase XmlWriter para llevar a cabo esa tarea.

En cualquier caso, no lo harías utilizando directamente la clase XmlReader para escribir elementos, sino utilizando los métodos de serialización destinados a convertir objetos en sus respectivos valores serializables, mediante la clase XmlSerializer:

  • learn.microsoft.com - Clase XmlSerializer (https://learn.microsoft.com/es-es/dotnet/api/system.xml.serialization.xmlserializer?view=net-7.0)
  • learn.microsoft.com - Uso de Visual C# para serializar un objeto en XML (https://learn.microsoft.com/es-es/troubleshoot/developer/visualstudio/csharp/language-compilers/serialize-object-xml)
  • learn.microsoft.com - Ejemplos de serialización XML (https://learn.microsoft.com/es-es/dotnet/standard/serialization/examples-of-xml-serialization)



En ciertos casos podrías recurrir a utilizar los correspondientes atributos de clase relacionados son la serialización de un tipo (clase o estructura, y sus miembros definidos) en formato Xml, e implementar la interfaz IXmlSerializable en dicho tipo, junto al uso de la clase XmlWriter (aquí, sí) para controlar y personalizar la serialización en formato Xml de sus miembros definidos.

Relacionado con esto, comparto aquí un ejemplo propio, de una clase por nombre "ColorString" que representa el valor de un color ARGB expresado en diferentes representaciones textuales. La clase implementa las interfaces ISerializable e IXmlSerializable:

https://pastebin.com/8C19nZFv (https://pastebin.com/8C19nZFv)

Nota: El código original está escrito en VB.NET; esto es una conversión automática del código a C#, probablemente haya errores de sintaxis en la consersión, y en cualquier caso NO es un código funcional (faltan referencias a otros miembros que no he añadido), es solo un ejemplo. Puedes encontrar otros ejemplos más reducidos y funcionales empezando por este:

  • learn.microsoft.com - Interfaz IXmlSerializable (https://learn.microsoft.com/es-es/dotnet/api/system.xml.serialization.ixmlserializable?view=net-7.0)



O quizás al mencionar los métodos getters/setters más bien te estés refiriendo a la estructura 'Settings' que se encarga de crear código autogenerado con las propiedades que especifiques (en la pestaña "Settings" de las propiedades de tu proyecto .NET 7.0) a través del archivo "app.config" para administrar la configuración de la aplicación.

Lo cierto es que, a menos que tengas alguna razón justificable por la cual prefieras guardar la configuración en formato Xml (o en json, o en binario, me es indiferente) 'Settings' es lo que deberías usar para guardar la configuración del usuario:

  • learn.microsoft.com - Introducción a la configuración de la aplicación (https://learn.microsoft.com/es-es/dotnet/desktop/winforms/advanced/application-settings-overview)
  • learn.microsoft.com - Administración de la configuración de la aplicación (.NET) (https://learn.microsoft.com/es-es/visualstudio/ide/managing-application-settings-dotnet)
  • learn.microsoft.com - Utilizar valores de configuración de aplicación y de usuario (https://learn.microsoft.com/es-es/dotnet/desktop/winforms/advanced/using-application-settings-and-user-settings)

PD: Esta característica está disponible desde que surgió .NET 2.0; En caso de que esto sea a lo que te estuvieses refiriendo, decir que hasta ahora estabas usando "la forma antigua" con Xml no sería muy excusable por parte de quien te haya enseñado esa forma :xD, pero tampoco por parte tuya.



Por que no usar json ? si quieres modernizarte, puedes usar : SettingsProvider.net (https://github.com/JakeGinnivan/SettingsProvider.net) es el que uso en todas mis apps , es realmente bueno.

No lo conocía. ¡Lo probaré a ver que tal!.

Ya que estamos hablando de formas para administrar la configuración del usuario, me gustaría aportar otra alternativa diferente de utilizar JSON para llevar a cabo esa función:

  • Jot - a .NET library for state persistence (https://github.com/anakic/Jot)

Cita del autor:
"Con Jot, solo necesita declarar qué propiedades de qué objetos desea rastrear y cuándo conservar y aplicar los datos."

Esto implica que no tenemos que escribir ningún código adicional para obtener ni asignar directamente los valores de la configuración. Eso se realiza de forma abstracta, sofistacadamente.

Es muy versatil y, además, ofrece simplicidad de uso mediante el patrón de diseño de interfaz fluida (Fluent interface) que nos permite encadenar varias sentencias en pocas líneas para controlar y condicionar, con belleza y precisión, el funcionamiento y el comportamiento de carga y guardado de los valores de la configuración, pudiendo asignar nombres de eventos en los que se ha de guardar un valor de la configuración, o condiciones especiales para no hacerlo, entre otras cosas, y aislando prácticamente toda esta lógica del código fuente de la interfaz de usuario.


Título: Re: Mejor guardado para XML
Publicado por: Meta en 10 Marzo 2024, 04:06 am
Muchas gracias a los dos, muy buena info.  ;-)

Ya que estamos, lo he hecho con archivos de txt en el cual a nadie le interesa pero funciona.

Código
  1. namespace Guardar_y_cargar_datos_en_archivo.txt_.NET_7._0
  2. {
  3.    public partial class Form1 : Form
  4.    {
  5.        public Form1()
  6.        {
  7.            InitializeComponent();
  8.        }
  9.  
  10.        private void Form1_Load(object sender, EventArgs e)
  11.        {
  12.            CargarControles();
  13.        }
  14.  
  15.        void GuardarCrontoles()
  16.        {
  17.            string archivoDeTexto = "";
  18.            int numero = 0;
  19.  
  20.            foreach (Control control in this.Controls)
  21.            {
  22.                if (control is Button)
  23.                    continue;
  24.                else if (control is TextBox)
  25.                    archivoDeTexto += (numero++).ToString() + ": " + ((TextBox)control).Text + "\n";
  26.                else if (control is CheckBox)
  27.                    archivoDeTexto += (numero++).ToString() + ": " + ((CheckBox)control).Checked + "\n";
  28.                else if (control is RadioButton)
  29.                    archivoDeTexto += (numero++).ToString() + ": " + ((RadioButton)control).Checked + "\n";
  30.                else if (control is GroupBox)
  31.                    foreach (Control ctrl in ((GroupBox)control).Controls)
  32.                        if (ctrl is TextBox)
  33.                            archivoDeTexto += (numero++).ToString() + ": " + ((TextBox)ctrl).Text + "\n";
  34.                        else if (ctrl is CheckBox)
  35.                            archivoDeTexto += (numero++).ToString() + ": " + ((CheckBox)ctrl).Text + "\n";
  36.                        else if (ctrl is RadioButton)
  37.                            archivoDeTexto += (numero++).ToString() + ": " + ((RadioButton)ctrl).Text + "\n";
  38.            }
  39.  
  40.            // Guardar archivo de texto en Controles.txt.
  41.            File.WriteAllText("Controles.txt", archivoDeTexto);
  42.        }
  43.  
  44.        void CargarControles()
  45.        {
  46.            int numero = 0;
  47.            string[] lineas;
  48.  
  49.            if (File.Exists("Controles.txt"))
  50.                lineas = File.ReadAllLines("Controles.txt");
  51.            else
  52.                return;
  53.  
  54.            foreach (Control control in this.Controls)
  55.            {
  56.                if (control is Button)
  57.                    continue;
  58.                else if (control is TextBox)
  59.                    ((TextBox)control).Text = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0));
  60.                else if (control is CheckBox)
  61.                    ((CheckBox)control).Checked = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0)) == "True" ? true : false;
  62.                else if (control is RadioButton)
  63.                    ((RadioButton)control).Checked = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0)) == "True" ? true : false;
  64.                else if (control is GroupBox)
  65.                    foreach (Control ctrl in ((GroupBox)control).Controls)
  66.                        if (ctrl is TextBox)
  67.                            ((TextBox)ctrl).Text = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0));
  68.                        else if (ctrl is CheckBox)
  69.                            ((CheckBox)ctrl).Checked = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0)) == "True" ? true : false;
  70.                        else if (ctrl is RadioButton)
  71.                            ((RadioButton)ctrl).Checked = lineas[numero++].Substring(3 + (numero >= 10 ? 1 : 0)) == "True" ? true : false;
  72.            }
  73.        }
  74.  
  75.        private void button_Guardar_Click(object sender, EventArgs e)
  76.        {
  77.            GuardarCrontoles();
  78.        }
  79.    }
  80. }

Y como dice arriba el compañero. ¿Por qué no json?

Pues también funciona.

Código
  1. using System.Text.Json;
  2.  
  3. namespace Guardar_y_cargar_datos_en_archivo.json_.NET_7._0___02
  4. {
  5.    public partial class Form1 : Form
  6.    {
  7.        public Form1()
  8.        {
  9.            InitializeComponent();
  10.        }
  11.  
  12.        class MiInfo
  13.        {
  14.            public string? TextBox { get; set; }
  15.            public bool CheckBox { get; set; }
  16.            public bool RadioButton1_Luz { get; set; }
  17.            public bool RadioButton2_Luz { get; set; }
  18.        }
  19.  
  20.        // Guardar datos en el archivo Ejemplo.json.
  21.        void GuardarDatos()
  22.        {
  23.            MiInfo miInfo = new()
  24.            {
  25.                TextBox = textBox1.Text,
  26.                CheckBox = checkBox1.Checked,
  27.                RadioButton1_Luz = radioButton1.Checked,
  28.                RadioButton2_Luz = radioButton2.Checked
  29.            };
  30.  
  31.                // Guardar con espacios en blanco el archivo .json.
  32.                var opciones = new JsonSerializerOptions { WriteIndented = true };
  33.                string serializado = JsonSerializer.Serialize(miInfo, opciones);
  34.  
  35.                // Crear archivo Ejemplo.json.
  36.                File.WriteAllText(@"Ejemplo.json", serializado);
  37.        }
  38.  
  39.        // Cargar datos en el archivo Ejemplo.json.
  40.        void CargarDatos()
  41.        {
  42.            // ¿Existe el archivo Ejemplo.json?
  43.            // if (File.Exists(@"Ejemplo.json") == true)
  44.            if (File.Exists(@"Ejemplo.json"))
  45.            {
  46.                // Sí. Lee el archivo completo.
  47.                string serializado = File.ReadAllText(@"Ejemplo.json");
  48.                MiInfo? miInfo = JsonSerializer.Deserialize<MiInfo>(serializado);
  49.  
  50.                // ¿Es distinto a nulo?
  51.                if (miInfo != null)
  52.                {
  53.                    // Sí. Lee los datos del archivo Ejemplo.json y los carga
  54.                    // en sus componentes indicados.
  55.                    textBox1.Text = miInfo.TextBox;
  56.                    checkBox1.Checked = miInfo.CheckBox;
  57.                    radioButton1.Checked = miInfo.RadioButton1_Luz;
  58.                    radioButton2.Checked = miInfo.RadioButton2_Luz;
  59.                }
  60.            }
  61.        }
  62.  
  63.        private void button_Guardar_Click(object sender, EventArgs e)
  64.        {
  65.            GuardarDatos();
  66.        }
  67.  
  68.        private void Form1_Load(object sender, EventArgs e)
  69.        {
  70.            CargarDatos();
  71.        }
  72.    }
  73. }

Contenido del json.
Código
  1. {
  2.  "TextBox": "Hola amigo.",
  3.  "CheckBox": false,
  4.  "RadioButton1_Luz": false,
  5.  "RadioButton2_Luz": true
  6. }

Salu2.  :D