AYUDA .NET

NServiceBus C# (Cómo funciona para desarrolladores)

Actualizado agosto 13, 2024
Compartir:

Introducción

NServiceBus es un bus de servicios potente y adaptable diseñado para .NET Framework que agiliza el desarrollo de sistemas distribuidos. Los sólidos patrones de mensajería que ofrece garantizan una gestión y entrega de mensajes fiables en varios microservicios y aplicaciones. NServiceBus abstrae la arquitectura de mensajería subyacente, lo que permite a los desarrolladores concentrarse en la lógica empresarial en lugar de en los entresijos de la creación de sistemas distribuidos.

En cambio, IronPDF es una conocida biblioteca .NET para generar, visualizar y modificar archivos PDF. Es bien conocido por ser fácil de usar y muy eficaz a la hora de crear PDF a partir de diversas fuentes, como archivos ASPX y HTML.

Los desarrolladores pueden crear sistemas de software fiables, escalables y mantenibles que puedan generar y gestionar documentos PDF como parte de sus operaciones empresariales combinando NServiceBus c e IronPDF.

En este artículo veremos cómo configurar un sencillo proyecto NServiceBus en C# e integrarlo con IronPDF, de modo que pueda crear un flujo de trabajo optimizado para gestionar y producir documentos PDF en una arquitectura de aplicación distribuida. Después de leer este tutorial de introducción, debería saber exactamente cómo estas dos eficaces tecnologías pueden cooperar para simplificar sus tareas relacionadas con PDF en un entorno distribuido.

¿Qué es NServiceBus c#?

NServiceBus es un marco potente y adaptable que facilita la creación de sistemas distribuidos y arquitecturas .NET orientadas a servicios. Utilizando NServiceBus, puede gestionar fácilmente varios tipos de mensajes y garantizar una comunicación fiable. Esto es crucial, sobre todo en una aplicación web y arquitecturas similares en las que el enrutamiento y el procesamiento de mensajes sin fisuras son esenciales. Los gestores de mensajes de NServiceBus se ocupan eficazmente de la recepción de mensajes, garantizando que todos los componentes lógicos interactúen sin problemas. NServiceBus tiene las siguientes características importantes:

NServiceBus C# (Cómo funciona para desarrolladores): Figura 1 - NServiceBus C#

Características de NServicebus

Comunicación basada en mensajes

NServiceBus fomenta la comunicación basada en mensajes entre los distintos servicios o componentes de un sistema. Al desacoplar los componentes, este método crea diseños más fáciles de escalar y gestionar.

Mensajería fiable

Al gestionar automáticamente los reintentos, las colas de espera y otras técnicas de tolerancia a fallos, garantiza una entrega fiable de los mensajes. En los sistemas distribuidos, donde son frecuentes los cortes de red y otros problemas de fallo, esta fiabilidad es esencial.

Modelo de publicación/suscripción

NServiceBus admite el patrón publicar/suscribir, lo que permite a los servicios publicar eventos y dejar que otros servicios se suscriban a ellos. Esto hace posibles las arquitecturas basadas en eventos, en las que las modificaciones introducidas en los eventos de un componente del sistema pueden provocar respuestas en otros componentes.

Saga Gestión

Los procesos empresariales de larga duración pueden gestionarse con NServiceBus gracias a su soporte integrado para sagas. Las sagas hacen posible que la plataforma de servicios gestione el estado y coordine operaciones intrincadas entre varios servicios.

Extensibilidad y personalización

Ofrece un nivel excepcional de extensibilidad, lo que permite a los desarrolladores personalizar el proceso de tratamiento, procesamiento y transporte de los mensajes. Gracias a su adaptabilidad, puede utilizarse en diversos escenarios.

Integración con varias plataformas de mensajería

Numerosos sistemas de mensajería, incluidos MSMQ, RabbitMQ, Azure Service Bus, Amazon SQS y otros, pueden integrarse con NServiceBus. Esto permite a los desarrolladores seleccionar la solución de infraestructura de comunicaciones que mejor se adapte a sus necesidades.

Crear y configurar NServiceBus en C#

Primero debe configurar su entorno de desarrollo, crear un proyecto básico y construir un servicio de mensajería básico y un escenario antes de poder empezar a utilizar NServiceBus en un proyecto de C#. Aquí tienes una guía paso a paso para ponerte en marcha.

Crear un nuevo proyecto de Visual Studio

En Visual Studio, el proceso de creación de un proyecto de consola es sencillo. Siga estos sencillos pasos en el entorno Visual Studio para lanzar una aplicación de consola:

Asegúrate de haber instalado Visual Studio en tu PC antes de utilizarlo.

Iniciar un nuevo proyecto

Haga clic en Archivo, seleccione Nuevo y, por último, Proyecto.

NServiceBus C# (Cómo funciona para desarrolladores): Figura 2 - Haga clic en "Nuevo"

Puede seleccionar la "Aplicación Consola" o la "Aplicación Consola" (.NET Core)" de la lista de referencias de plantillas de proyectos que figura a continuación.

Introduzca un nombre para su proyecto en el campo "Nombre".

NServiceBus C# (Cómo funciona para desarrolladores): Figura 3 - Proporcione un nombre y una ubicación para el proyecto

Elige un lugar de almacenamiento para el proyecto.

Al hacer clic en "Crear" se iniciará el proyecto de la aplicación Consola.

NServiceBus C# (Cómo funciona para desarrolladores): Figura 4 - Haga clic en "crear"

Instalar paquetes NServiceBus

Vaya a Herramientas > Gestor de paquetes NuGet > Consola del gestor de paquetes para abrir la Consola del gestor de paquetes NuGet.

Ejecute el siguiente comando para instalar el paquete NServiceBus NuGet.

Install-Package NServiceBus
Install-Package NServiceBus
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Elija un transporte

NServiceBus necesita el transporte para recibir y enviar mensajes. Nos quedaremos con el Learning Transport, ya que es fácil de usar y funciona bien para pruebas y desarrollo.

Instale el paquete para Learning Transport ejecutando.

Install-Package NServiceBus.RabbitMQ
Install-Package NServiceBus.RabbitMQ
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Configurar NServiceBus

Configurar el punto final

Establezca la configuración del punto final NServiceBus en su archivo Program.cs:

using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
class Program
{
    static async Task Main()
    {
        Console.Title = "Sender";
        var endpointConfiguration = new EndpointConfiguration("SenderEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to send a message...");
        Console.ReadLine();
        // Send a message
        var message = new MyMessage
        {
            Content = "Hello, NServiceBus with RabbitMQ!"
        };
        await endpointInstance.Send("ReceiverEndpoint", message)
            .ConfigureAwait(false);
        Console.WriteLine("Message sent. Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
class Program
{
    static async Task Main()
    {
        Console.Title = "Sender";
        var endpointConfiguration = new EndpointConfiguration("SenderEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to send a message...");
        Console.ReadLine();
        // Send a message
        var message = new MyMessage
        {
            Content = "Hello, NServiceBus with RabbitMQ!"
        };
        await endpointInstance.Send("ReceiverEndpoint", message)
            .ConfigureAwait(false);
        Console.WriteLine("Message sent. Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

NServiceBus C# (Cómo funciona para desarrolladores): Figura 5 - Ejemplo de salida de la consola

Crear un mensaje

Para representar el mensaje, añada una nueva clase.

public class MyMessage : IMessage
{
    public string Content { get; set; }
}
public class MyMessage : IMessage
{
    public string Content { get; set; }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Crear un gestor de mensajes

Para gestionar el mensaje, añade una nueva clase.

using NServiceBus;
using System.Threading.Tasks;
public class MyMessageHandler : IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        Console.WriteLine($"Received message: {message.Content}");
        return Task.CompletedTask;
    }
}
using NServiceBus;
using System.Threading.Tasks;
public class MyMessageHandler : IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        Console.WriteLine($"Received message: {message.Content}");
        return Task.CompletedTask;
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Enviar un mensaje

Enviar un mensaje desde el Endpoint. Adapta tu forma principal de transmitir un mensaje con la ayuda del manipulador.

using NServiceBus;
using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
    Console.Title = "Receiver";
    var endpointConfiguration = new EndpointConfiguration("ReceiverEndpoint");
    endpointConfiguration.UseSerialization<NewtonsoftJsonSerializer>();
    // Use RabbitMQ Transport
    var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
    transport.UseConventionalRoutingTopology(QueueType.Quorum);
    transport.ConnectionString("host=localhost");
    // Set up error queue
    endpointConfiguration.SendFailedMessagesTo("error");
    // Set up audit queue
    endpointConfiguration.AuditProcessedMessagesTo("audit");
    endpointConfiguration.EnableInstallers();
    // Start the endpoint
    var endpointInstance = await Endpoint.Start(endpointConfiguration)
                .ConfigureAwait(false);
    Console.WriteLine("Press Enter to exit...");
    Console.ReadLine();
    // Stop the endpoint
    await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
using NServiceBus;
using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
    Console.Title = "Receiver";
    var endpointConfiguration = new EndpointConfiguration("ReceiverEndpoint");
    endpointConfiguration.UseSerialization<NewtonsoftJsonSerializer>();
    // Use RabbitMQ Transport
    var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
    transport.UseConventionalRoutingTopology(QueueType.Quorum);
    transport.ConnectionString("host=localhost");
    // Set up error queue
    endpointConfiguration.SendFailedMessagesTo("error");
    // Set up audit queue
    endpointConfiguration.AuditProcessedMessagesTo("audit");
    endpointConfiguration.EnableInstallers();
    // Start the endpoint
    var endpointInstance = await Endpoint.Start(endpointConfiguration)
                .ConfigureAwait(false);
    Console.WriteLine("Press Enter to exit...");
    Console.ReadLine();
    // Stop the endpoint
    await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

NServiceBus C# (Cómo funciona para desarrolladores): Figura 6 - Ejemplo de salida de consola

Inicie la aplicación y cree el proyecto. La consola debería mostrar el mensaje "Received message: Hola, NServiceBus!"

Primeros pasos

En un proyecto de C#, la integración de NServiceBus con RabbitMQ e IronPDF implica la configuración de mensajes entre NServiceBus y RabbitMQ, así como el uso de IronPDF para crear archivos PDF. Aquí tienes una guía completa para ponerte en marcha:

¿Qué es IronPDF?

IronPDF es una biblioteca .NET diseñada para crear, leer, editar y convertir archivos PDF. Con ella, los programadores pueden trabajar con archivos PDF en aplicaciones C# o VB.NET con una herramienta potente e intuitiva. A continuación se describen detalladamente las características y funciones de IronPDF:

NServiceBus C# (Cómo funciona para desarrolladores): Figura 7 - IronPDF: Página de inicio de la biblioteca PDP de C#

Características de IronPDF

Generación de PDF a partir de HTML

Convierte JavaScript, HTML y CSS a PDF. es compatible con media queries y responsive design, dos estándares web contemporáneos. útil para producir documentos PDF, facturas e informes con estilo dinámico utilizando HTML y CSS.

Edición de PDF

A los PDF ya existentes, añada texto, imágenes y otros materiales. Extraiga texto e imágenes de archivos PDF. Combinar varios PDF en un solo archivo. Divide archivos PDF en varios documentos. Incluya anotaciones, pies de página, encabezados y marcas de agua.

Conversión de PDF

Convierte Word, Excel, imágenes y otros formatos de archivo a PDF. Conversión de PDF a imagen (PNG, JPEG, etc.).

**Rendimiento y fiabilidad

El alto rendimiento y la fiabilidad son los objetivos de diseño en los entornos de producción. gestiona eficazmente documentos de gran tamaño.

Instalación de IronPDF

Instale IronPDF abriendo la consola del gestor de paquetes NuGet.

Install-Package IronPdf
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'Install-Package IronPdf
VB   C#

Configurar el remitente con mensaje

Mensajes es un proyecto compartido (biblioteca de clases) que utilizarán tanto el remitente como el destinatario. Defina la clase de mensaje en el proyecto Mensajes. Cree un nuevo proyecto de biblioteca de clases llamado Mensajes y añádalo a la solución.

Definir el mensaje:

Dentro del proyecto Mensajes, cree una nueva clase llamada GenerarMensajePdf.cs:

using NServiceBus;
public class GeneratePdfMessage : IMessage
{
    public string Content { get; set; }
    public string OutputPath { get; set; }
}
using NServiceBus;
public class GeneratePdfMessage : IMessage
{
    public string Content { get; set; }
    public string OutputPath { get; set; }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Tanto en el proyecto Emisor como en el Receptor, incluya una referencia al proyecto Mensajes.

Configure el endpoint NServiceBus en el proyecto Sender para utilizar RabbitMQ para la entrega de mensajes.

using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
class Program
{
    static async Task Main()
    {
        Console.Title = "Sender";
        var endpointConfiguration = new EndpointConfiguration("SenderEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
    endpointConfiguration.EnableInstallers();
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to send a message...");
        Console.ReadLine();
        // Send a message
        var message = new GeneratePdfMessage
        {
            Content = "<h1>Hello, NServiceBus with RabbitMQ and IronPDF!</h1>",
            OutputPath = "output.pdf"
        };
        await endpointInstance.Send("ReceiverEndpoint", message)
            .ConfigureAwait(false);
        Console.WriteLine("Message sent. Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
class Program
{
    static async Task Main()
    {
        Console.Title = "Sender";
        var endpointConfiguration = new EndpointConfiguration("SenderEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
    endpointConfiguration.EnableInstallers();
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to send a message...");
        Console.ReadLine();
        // Send a message
        var message = new GeneratePdfMessage
        {
            Content = "<h1>Hello, NServiceBus with RabbitMQ and IronPDF!</h1>",
            OutputPath = "output.pdf"
        };
        await endpointInstance.Send("ReceiverEndpoint", message)
            .ConfigureAwait(false);
        Console.WriteLine("Message sent. Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Configuración del punto final: el punto final se inicializa con el nombre "SenderEndpoint" llamando a new EndpointConfiguration("SenderEndpoint").

endpointConfiguration es la configuración de transporte. Al conectarse a una instancia local de RabbitMQ, el método UseTransport() configura NServiceBus para utilizar RabbitMQ como mecanismo de transporte.

Colas de auditoría y error El lugar al que se envían los mensajes fallidos y los mensajes procesados de auditoría se configura mediante SendFailedMessagesTo("error") y AuditProcessedMessagesTo("auditoría")respectivamente.

Mensaje enviado: endpointInstance.A GeneratePdfMessage se envía al "ReceiverEndpoint" a través de la función Send("ReceiverEndpoint", mensaje) función.

Configurar el receptor para generar PDF

Configure el endpoint NServiceBus en el proyecto Receiver para aceptar mensajes a través de RabbitMQ y producir PDFs utilizando IronPDF.

using NServiceBus;
using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        Console.Title = "Receiver";
        var endpointConfiguration = new EndpointConfiguration("ReceiverEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
using NServiceBus;
using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        Console.Title = "Receiver";
        var endpointConfiguration = new EndpointConfiguration("ReceiverEndpoint");
        // Use RabbitMQ Transport
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost");
        // Set up error queue
        endpointConfiguration.SendFailedMessagesTo("error");
        // Set up audit queue
        endpointConfiguration.AuditProcessedMessagesTo("audit");
        // Start the endpoint
        var endpointInstance = await Endpoint.Start(endpointConfiguration)
            .ConfigureAwait(false);
        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();
        // Stop the endpoint
        await endpointInstance.Stop()
            .ConfigureAwait(false);
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

Esta configuración, para el punto final receptor "ReceiverEndpoint", es comparable a la configuración Sender.

Gestor de mensajes

En el proyecto Receiver, cree una nueva clase llamada GeneratePdfMessageHandler.cs.

using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
using IronPdf;
public class GeneratePdfMessageHandler : IHandleMessages<GeneratePdfMessage>
{
    public Task Handle(GeneratePdfMessage message, IMessageHandlerContext context)
    {
        Console.WriteLine($"Received message to generate PDF with content: {message.Content}");
        // Generate PDF
        var renderer = new HtmlToPdf();
        var pdf = renderer.RenderHtmlAsPdf(message.Content);
        pdf.SaveAs(message.OutputPath);
        Console.WriteLine($"PDF generated and saved to: {message.OutputPath}");
        return Task.CompletedTask;
    }
}
using NServiceBus;
using System;
using System.Threading.Tasks;
using Messages;
using IronPdf;
public class GeneratePdfMessageHandler : IHandleMessages<GeneratePdfMessage>
{
    public Task Handle(GeneratePdfMessage message, IMessageHandlerContext context)
    {
        Console.WriteLine($"Received message to generate PDF with content: {message.Content}");
        // Generate PDF
        var renderer = new HtmlToPdf();
        var pdf = renderer.RenderHtmlAsPdf(message.Content);
        pdf.SaveAs(message.OutputPath);
        Console.WriteLine($"PDF generated and saved to: {message.OutputPath}");
        return Task.CompletedTask;
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
VB   C#

GeneratePdfMessage utilizando la interfaz IHandleMessages InterfaceHandler indica que manejará mensajes de tipo GenerarMensajePdf implementando una interfaz para IHandleMessages.

NServiceBus C# (Cómo funciona para desarrolladores): Figura 8 - Ejemplo de salida de consola

Aproximación a la gestión: Tras recibir el mensaje, la función Manejar crea un PDF utilizando IronPDF. El código del renderizador HtmlToPdf convierte el contenido HTML del mensaje en PDF y lo guarda en la ruta de salida designada.

NServiceBus C# (Cómo funciona para desarrolladores): Figura 9 - Salida PDF utilizando NServiceBus con RabbitMQ junto con IronPDf

Conclusión

NServiceBus puede integrarse con RabbitMQ e IronPDF en C# para proporcionar una solución escalable y estable a los sistemas distribuidos que necesitan generar PDF de forma dinámica y fiable. Esta combinación aprovecha las capacidades de procesamiento de mensajes de NServiceBus, la fiabilidad y adaptabilidad de RabbitMQ como intermediario de mensajes y las sólidas herramientas de edición de PDF de IronPDF. La arquitectura resultante garantiza el desacoplamiento entre servicios, lo que permite una evolución y escalabilidad autónomas.

RabbitMQ también garantiza la entrega de mensajes incluso en caso de fallos de la red o de la aplicación. NServiceBus simplifica el enrutamiento y procesamiento de mensajes, e IronPDF permite convertir texto HTML en documentos PDF de alta calidad. Esta integración ofrece un marco flexible para desarrollar aplicaciones sofisticadas a gran escala, además de mejorar el mantenimiento y la fiabilidad del sistema.

Por último, al añadir IronPDF y Iron Software a su conjunto de herramientas para la programación .NET, podrá trabajar eficazmente con códigos de barras, generar PDF, realizar OCR y enlazar con Excel. IronPDFa partir de 749 euros, combina a la perfección sus prestaciones con el rendimiento, la compatibilidad y la facilidad de uso de IronSoftwarepara ofrecer aplicaciones y funciones web adicionales y un desarrollo más eficaz.

Si existen opciones de licencia bien definidas y adaptadas a los requisitos específicos del proyecto, los desarrolladores pueden seleccionar el modelo óptimo con confianza. Estas ventajas permiten a los desarrolladores gestionar una serie de dificultades de forma eficaz y transparente.

< ANTERIOR
Flurl C# (Cómo funciona para desarrolladores)
SIGUIENTE >
C# Pass by Reference (Cómo funciona para desarrolladores)

¿Listo para empezar? Versión: 2024.9 acaba de salir

Descarga gratuita de NuGet Descargas totales: 10,516,730 View Licenses >