.NET-HILFE

CQRS-Muster C# (Wie es für Entwickler funktioniert)

Veröffentlicht 3. April 2024
Teilen Sie:

Einführung in CQRS

CQRS steht für Command Query Responsibility Segregation. Es handelt sich um ein Muster, bei dem das Lesen von Daten vom Schreiben getrennt wird. Diese Unterscheidung ist aus mehreren Gründen wichtig. Erstens ermöglicht es eine flexiblere Optimierung der einzelnen Vorgänge und verbessert so die Leistung und Skalierbarkeit der Anwendung. Wenn Sie Befehle trennen (schreibt) und Abfragen (liest)können Sie sie unabhängig voneinander optimieren.

Eine komplexe Anwendung kann zum Beispiel schnelle Lesevorgänge erfordern, aber langsamere Schreibvorgänge tolerieren. Durch die Anwendung von CQRS können Entwickler unterschiedliche Datenmodelle für Lese- und Schreibvorgänge verwenden und die Datenzugriffsschicht abtrennen, um sie an die spezifischen Anforderungen der einzelnen Vorgänge anzupassen. In diesem Artikel werden wir die Konzepte des CQRS-Musters und der IronPDF bibliothek.

Kernkonzepte und Komponenten

Der Kern von CQRS liegt in der Trennung von Befehls- und Abfrageoperationen, die jeweils unterschiedliche Aspekte der Dateninteraktion behandeln. Das Verständnis dieser Komponenten ist entscheidend für die effektive Umsetzung des Musters.

  • Befehle: Diese sind für die Aktualisierung der Daten zuständig. Befehle verkörpern komplexe Geschäftslogik und können den Zustand von Daten im Datenspeicher ändern, indem sie ohne Rückgabe von Informationen agieren. Befehle übernehmen die ausschließliche Aufgabe, Schreibaufgaben zu erledigen, und beeinflussen den Zustand der Anwendung direkt, ohne eine Ausgabe zu liefern. Das Hinzufügen eines neuen Benutzers oder das Aktualisieren von Produktdaten sind beispielsweise Aktionen, die durch Befehle ausgeführt werden.
  • Abfragen: Abfragen, die von einem Query-Handler verwaltet werden, rufen Daten oder Datenübertragungsobjekte ab, ohne den Zustand des Systems zu verändern. Das sind die Fragen, die Sie zu Ihren Daten stellen. Abfragen sind z. B. das Abrufen des Profils eines Benutzers oder die Auflistung aller in einem Bestand verfügbaren Produkte. Abfragen geben Daten zurück, stellen aber sicher, dass sie die Daten oder ihren Zustand nicht verändern.

    Eines der beliebtesten Tools zur Implementierung von CQRS in .NET-Anwendungen ist MediatR, eine Mediator-Pattern-Bibliothek. Sie trägt dazu bei, die Kopplung zwischen den Komponenten einer Anwendung zu verringern, so dass sie indirekt miteinander kommunizieren. MediatR erleichtert die Bearbeitung von Befehlen und Abfragen, indem es zwischen dem Befehl/der Abfrage und seinem Bearbeiter vermittelt.

Praktische Umsetzung mit ASP.NET Core

Bei der Implementierung des CQRS-Musters in ASP.NET Core müssen Sie Ihr Projekt so einrichten, dass Befehle und Abfragen voneinander getrennt werden, und eine Bibliothek wie MediatR verwenden, um zwischen ihnen zu vermitteln. Hier finden Sie eine vereinfachte Übersicht, wie Sie CQRS in Ihrer ASP.NET Core-Anwendung einrichten können.

Schritt 1: Einrichten Ihrer ASP.NET-Anwendung

  1. Starten Sie Visual Studio und wählen Sie die Option zum Erstellen eines neuen Projekts.

  2. Suchen Sie nach einem Projekttyp "ASP.NET Core Web Application" und wählen Sie ihn aus. Klicken Sie auf Weiter.

    CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 1 - Erstellen eines neuen ASP.NET-Projekts

  3. Geben Sie Ihrem Projekt einen Namen und legen Sie seinen Standort fest. Klicken Sie auf Erstellen.

  4. Wählen Sie die "Webanwendung (Modell-Ansichts-Steuerung)" Vorlage für ASP.NET Core. Stellen Sie sicher, dass Sie die .NET Core-Version verwenden, die Ihren Anforderungen entspricht. Klicken Sie auf Erstellen.

Schritt 2

Als nächstes müssen Sie Ihr Projekt für CQRS organisieren. Sie können dies tun, indem Sie Ordner hinzufügen, um Befehle, Abfragen und die gemeinsamen Schnittstellen, die sie verwenden, zu trennen. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Ihr Projekt und wählen Sie "Hinzufügen" und dann "Neuer Ordner". Erstellen Sie drei Verzeichnisse: "Befehle", "Abfragen" und "Schnittstellen".

Fügen Sie im Ordner "Interfaces" Schnittstellen für Ihre Befehle und Abfragen hinzu. Für einen Befehl können Sie eine Schnittstelle ICommandHandler mit einer Methode Handle haben, die einen Befehl aufnimmt und die Aktion ausführt. Für eine Abfrage könnte man eine Schnittstelle IQueryHandler mit einer Methode Handle haben, die eine Abfrage aufnimmt und Daten zurückgibt.

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 2 - Beispiel, wie Dateien organisiert werden könnten

Schritt 3

Fügen wir nun zur Veranschaulichung einen Befehl und eine Abfrage hinzu. Angenommen, Ihre Anwendung verwaltet Aufgaben, und Sie möchten eine Aufgabe hinzufügen (befehl) und Aufgaben abrufen (abfrage).

Fügen Sie im Ordner "Interfaces" zwei Schnittstellen hinzu:

//Define interfaces for your handlers:
public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}
public interface IQueryHandler<TQuery, TResult>
{
    TResult Handle(TQuery query);
}
//Define interfaces for your handlers:
public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}
public interface IQueryHandler<TQuery, TResult>
{
    TResult Handle(TQuery query);
}
'Define interfaces for your handlers:
Public Interface ICommandHandler(Of TCommand)
	Sub Handle(ByVal command As TCommand)
End Interface
Public Interface IQueryHandler(Of TQuery, TResult)
	Function Handle(ByVal query As TQuery) As TResult
End Interface
VB   C#

Fügen Sie im Ordner "Commands" eine Klasse AddItemCommand mit Eigenschaften für die Aufgabendetails hinzu. Fügen Sie außerdem eine Klasse AddItemCommandHandler hinzu, die ICommandHandler implementiert und die Logik zum Hinzufügen einer Aufgabe zur Datenbank enthält.

Fügen Sie im Ordner "Queries" eine Klasse GetTasksQuery hinzu, die eine Anfrage nach Aufgaben darstellt. Fügen Sie eine weitere Klasse GetTasksQueryHandler hinzu, die IQueryHandler implementiert und die Logik zum Abrufen von Aufgaben aus der Datenbank enthält.

Ein einfaches Beispiel: Ihr AddItemCommand könnte wie folgt aussehen:

public class AddItemCommand
{
    public string Name { get; set; }
    public int Quantity { get; set; }
    // Constructor
    public AddItemCommand(string name, int quantity)
    {
        Name = name;
        Quantity = quantity;
    }
}
public class AddItemCommand
{
    public string Name { get; set; }
    public int Quantity { get; set; }
    // Constructor
    public AddItemCommand(string name, int quantity)
    {
        Name = name;
        Quantity = quantity;
    }
}
Public Class AddItemCommand
	Public Property Name() As String
	Public Property Quantity() As Integer
	' Constructor
	Public Sub New(ByVal name As String, ByVal quantity As Integer)
		Me.Name = name
		Me.Quantity = quantity
	End Sub
End Class
VB   C#

Und der AddItemCommandHandler:

public class AddItemCommandHandler : ICommandHandler<AddItemCommand>
{
    public void Handle(AddItemCommand command)
    {
        // Here, you'd add the item to your database, for example, to have employee data stored
        Console.WriteLine($"Adding item: {command.Name} with quantity {command.Quantity}");
        // Add database logic here
    }
}
public class AddItemCommandHandler : ICommandHandler<AddItemCommand>
{
    public void Handle(AddItemCommand command)
    {
        // Here, you'd add the item to your database, for example, to have employee data stored
        Console.WriteLine($"Adding item: {command.Name} with quantity {command.Quantity}");
        // Add database logic here
    }
}
Public Class AddItemCommandHandler
	Implements ICommandHandler(Of AddItemCommand)

	Public Sub Handle(ByVal command As AddItemCommand)
		' Here, you'd add the item to your database, for example, to have employee data stored
		Console.WriteLine($"Adding item: {command.Name} with quantity {command.Quantity}")
		' Add database logic here
	End Sub
End Class
VB   C#

Ihre GetItemsQuery könnte leer sein, wenn sie keine Parameter zum Abrufen von Aufgaben benötigt, und GetItemsQueryHandler könnte wie folgt aussehen:

public class GetItemsQuery
{
    // This class might not need any properties, depending on your query
}
using CQRS_testing.Interfaces;
namespace CQRS_testing.Queries
{
    public class GetItemsQueryHandler : IQueryHandler<GetItemsQuery, IEnumerable<string>>
    {
        public IEnumerable<string> Handle(GetItemsQuery query)
        {
            // Here, you'd fetch items from your database
            return new List<string> { "Item1", "Item2" };
        }
    }
}
public class GetItemsQuery
{
    // This class might not need any properties, depending on your query
}
using CQRS_testing.Interfaces;
namespace CQRS_testing.Queries
{
    public class GetItemsQueryHandler : IQueryHandler<GetItemsQuery, IEnumerable<string>>
    {
        public IEnumerable<string> Handle(GetItemsQuery query)
        {
            // Here, you'd fetch items from your database
            return new List<string> { "Item1", "Item2" };
        }
    }
}
Imports CQRS_testing.Interfaces

Public Class GetItemsQuery
	' This class might not need any properties, depending on your query
End Class
Namespace CQRS_testing.Queries
	Public Class GetItemsQueryHandler
		Implements IQueryHandler(Of GetItemsQuery, IEnumerable(Of String))

		Public Function Handle(ByVal query As GetItemsQuery) As IEnumerable(Of String)
			' Here, you'd fetch items from your database
			Return New List(Of String) From {"Item1", "Item2"}
		End Function
	End Class
End Namespace
VB   C#

In Ihren ASP.NET-Controllern werden Sie diese Handler verwenden, um Befehle und Abfragen zu verarbeiten. Um eine Aufgabe hinzuzufügen, würde die Controller-Aktion einen AddTaskCommand erstellen, seine Eigenschaften anhand der Formulardaten festlegen und ihn dann zur Bearbeitung an eine AddTaskCommandHandler-Instanz übergeben. Zum Abrufen von Aufgaben würde ein GetTasksQueryHandler aufgerufen, um die Daten abzurufen und sie an die Ansicht zu übergeben.

Verdrahtung in einer Steuerung

Nachdem Sie Ihre Befehle und Abfragen eingerichtet haben, können Sie sie nun in Ihren Steuerungen verwenden. Hier sehen Sie, wie Sie das in einer ItemsController-Klasse tun können:

public class ItemsController : Controller
{
    private readonly ICommandHandler<AddItemCommand> _addItemHandler;
    private readonly IQueryHandler<GetItemsQuery, IEnumerable<string>> _getItemsHandler;
    // Constructor injection is correctly utilized here
    public ItemsController(ICommandHandler<AddItemCommand> addItemHandler, IQueryHandler<GetItemsQuery, IEnumerable<string>> getItemsHandler)
    {
        _addItemHandler = addItemHandler;
        _getItemsHandler = getItemsHandler;
    }
    public IActionResult Index()
    {
        // Use the injected _getItemsHandler instead of creating a new instance
        var query = new GetItemsQuery();
        var items = _getItemsHandler.Handle(query);
        return View(items);
    }
    [HttpPost]
    public IActionResult Add(string name, int quantity)
    {
        // Use the injected _addItemHandler instead of creating a new instance
        var command = new AddItemCommand(name, quantity);
        _addItemHandler.Handle(command);
        return RedirectToAction("Index");
    }
}
public class ItemsController : Controller
{
    private readonly ICommandHandler<AddItemCommand> _addItemHandler;
    private readonly IQueryHandler<GetItemsQuery, IEnumerable<string>> _getItemsHandler;
    // Constructor injection is correctly utilized here
    public ItemsController(ICommandHandler<AddItemCommand> addItemHandler, IQueryHandler<GetItemsQuery, IEnumerable<string>> getItemsHandler)
    {
        _addItemHandler = addItemHandler;
        _getItemsHandler = getItemsHandler;
    }
    public IActionResult Index()
    {
        // Use the injected _getItemsHandler instead of creating a new instance
        var query = new GetItemsQuery();
        var items = _getItemsHandler.Handle(query);
        return View(items);
    }
    [HttpPost]
    public IActionResult Add(string name, int quantity)
    {
        // Use the injected _addItemHandler instead of creating a new instance
        var command = new AddItemCommand(name, quantity);
        _addItemHandler.Handle(command);
        return RedirectToAction("Index");
    }
}
Public Class ItemsController
	Inherits Controller

	Private ReadOnly _addItemHandler As ICommandHandler(Of AddItemCommand)
	Private ReadOnly _getItemsHandler As IQueryHandler(Of GetItemsQuery, IEnumerable(Of String))
	' Constructor injection is correctly utilized here
	Public Sub New(ByVal addItemHandler As ICommandHandler(Of AddItemCommand), ByVal getItemsHandler As IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)))
		_addItemHandler = addItemHandler
		_getItemsHandler = getItemsHandler
	End Sub
	Public Function Index() As IActionResult
		' Use the injected _getItemsHandler instead of creating a new instance
		Dim query = New GetItemsQuery()
		Dim items = _getItemsHandler.Handle(query)
		Return View(items)
	End Function
	<HttpPost>
	Public Function Add(ByVal name As String, ByVal quantity As Integer) As IActionResult
		' Use the injected _addItemHandler instead of creating a new instance
		Dim command = New AddItemCommand(name, quantity)
		_addItemHandler.Handle(command)
		Return RedirectToAction("Index")
	End Function
End Class
VB   C#

Um alles zu verdrahten, insbesondere wenn Sie Dependency Injection verwenden (DI) in ASP.NET Core müssen Sie Ihre Befehls- und Abfrage-Handler mit dem DI-Container in der Datei Startup.cs registrieren. Auf diese Weise kann ASP.NET Instanzen Ihrer Handler bereitstellen, wenn sie benötigt werden.

Hier ist ein sehr einfaches Beispiel für die Registrierung eines Handlers:

builder.Services.AddTransient<ICommandHandler<AddItemCommand>, AddItemCommandHandler>();
builder.Services.AddTransient<IQueryHandler<GetItemsQuery, IEnumerable<string>>, GetItemsQueryHandler>();
builder.Services.AddTransient<ICommandHandler<AddItemCommand>, AddItemCommandHandler>();
builder.Services.AddTransient<IQueryHandler<GetItemsQuery, IEnumerable<string>>, GetItemsQueryHandler>();
builder.Services.AddTransient(Of ICommandHandler(Of AddItemCommand), AddItemCommandHandler)()
builder.Services.AddTransient(Of IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)), GetItemsQueryHandler)()
VB   C#

In der praktischen Anwendung von CQRS ist die Unterscheidung zwischen dem Datenmodell für Schreiboperationen und dem für Leseoperationen von grundlegender Bedeutung, da sie sicherstellt, dass die Architektur unterschiedliche und optimierte Ansätze für den Umgang mit Daten unterstützt.

IronPDF: C# PDF-Bibliothek

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 3 - IronPDF-Webseite

IronPDF ist ein Werkzeug für Entwickler, die mit der Programmiersprache C# arbeiten, mit dem sie PDF-Dokumente direkt in ihren Anwendungen erstellen, lesen und bearbeiten können. Diese Bibliothek ist benutzerfreundlich und vereinfacht die Integration von PDF-Funktionen wie die Erstellung von PDF-Berichten, Rechnungen oder Formulare aus HTML code. IronPDF unterstützt verschiedene Funktionen, darunter die Bearbeitung von Text und Bildern in PDF-Dateien, die Einrichtung der Dokumentensicherheit und die Konvertierung von Webseiten in das PDF-Format. Seine Vielseitigkeit und Benutzerfreundlichkeit machen es zu einer wertvollen Ressource für Entwickler, die PDF-Operationen in ihren Projekten implementieren möchten.

IronPDF zeichnet sich durch seine HTML zu PDF fähigkeit, wobei alle Layouts und Stile intakt bleiben. Es erstellt PDFs aus Webinhalten, die sich für Berichte, Rechnungen und Dokumentationen eignen. HTML-Dateien, URLs und HTML-Strings können nahtlos in PDFs konvertiert werden.

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
VB   C#

Code-Beispiel

Lassen Sie uns nun untersuchen, wie IronPDF innerhalb einer C#-Anwendung nach der Command Query Responsibility Segregation genutzt werden kann (CQRS) muster. Nachfolgend finden Sie ein vereinfachtes Beispiel, das zeigt, wie Sie IronPDF innerhalb einer CQRS-Einrichtung zur Erstellung eines PDF-Berichts verwenden können. Dieses Beispiel ist konzeptionell und konzentriert sich auf die Erzeugung eines PDF-Dokuments als Befehl.

using IronPdf;
using System.Threading.Tasks;
namespace PdfGenerationApp.Commands
{
    public class GeneratePdfReportCommand
    {
        // Command handler that generates a PDF report
        public async Task GenerateReportAsync(string reportContent, string outputPath)
        {
            // Initialize the IronPDF HTML to PDF renderer
            var renderer = new ChromePdfRenderer();
            // Use IronPDF to generate a PDF from HTML content
            var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(reportContent));
            // Save the generated PDF to a specified path
            pdf.SaveAs(outputPath);
        }
    }
}
using IronPdf;
using System.Threading.Tasks;
namespace PdfGenerationApp.Commands
{
    public class GeneratePdfReportCommand
    {
        // Command handler that generates a PDF report
        public async Task GenerateReportAsync(string reportContent, string outputPath)
        {
            // Initialize the IronPDF HTML to PDF renderer
            var renderer = new ChromePdfRenderer();
            // Use IronPDF to generate a PDF from HTML content
            var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(reportContent));
            // Save the generated PDF to a specified path
            pdf.SaveAs(outputPath);
        }
    }
}
Imports IronPdf
Imports System.Threading.Tasks
Namespace PdfGenerationApp.Commands
	Public Class GeneratePdfReportCommand
		' Command handler that generates a PDF report
		Public Async Function GenerateReportAsync(ByVal reportContent As String, ByVal outputPath As String) As Task
			' Initialize the IronPDF HTML to PDF renderer
			Dim renderer = New ChromePdfRenderer()
			' Use IronPDF to generate a PDF from HTML content
			Dim pdf = Await Task.Run(Function() renderer.RenderHtmlAsPdf(reportContent))
			' Save the generated PDF to a specified path
			pdf.SaveAs(outputPath)
		End Function
	End Class
End Namespace
VB   C#

In diesem Beispiel stellt GeneratePdfReportCommand einen Befehl nach dem CQRS-Muster dar. Sie enthält eine Methode GenerateReportAsync, die reportContent als HTML-String und einen outputPath, unter dem der PDF-Bericht gespeichert wird, entgegennimmt. Die Klasse HtmlToPdf von IronPDF wird verwendet, um den HTML-Inhalt in das PDF-Format zu konvertieren, das dann unter dem angegebenen Pfad gespeichert wird. Dieses Setup veranschaulicht, wie Sie PDF-Generierungsfunktionen in die Architektur Ihrer Anwendung integrieren können, insbesondere in Szenarien, die eine klare Trennung von Belangen erfordern, wie sie von CQRS gefördert wird.

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 4 - Ausgegebenes PDF

Schlussfolgerung

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 5 - IronPDF-Lizenzseite

Zusammenfassend lässt sich sagen, dass der Befehl Query Responsibility Segregation (CQRS) muster bietet einen strukturierten Ansatz, um die Verantwortlichkeiten für das Lesen und Schreiben von Daten in Ihren Anwendungen zu trennen. Diese Trennung verdeutlicht nicht nur die Architektur, sondern erhöht auch die Flexibilität, Skalierbarkeit und Leistung Ihrer Systeme. Wenn Sie die oben beschriebenen Schritte befolgen, können Sie CQRS in Ihre ASP.NET Core-Anwendungen implementieren und Tools wie MediatR verwenden, um die Kommunikation zwischen Befehlen, Abfragen und ihren Handlern zu optimieren.

Die Integration von IronPDF in Ihre CQRS-basierte Anwendung erweitert deren Möglichkeiten und ermöglicht Ihnen, mühelos PDF-Dokumente zu erstellen, zu bearbeiten und zu speichern. Ganz gleich, ob Sie Berichte, Rechnungen oder andere Dokumente erstellen, die umfassenden Funktionen und die einfache Syntax von IronPDF machen es zu einem leistungsstarken Werkzeug in Ihrem Entwicklungs-Toolkit. IronPDF bietet eine kostenlos testenso haben Sie die Möglichkeit, die Möglichkeiten des Systems zu testen, bevor Sie sich festlegen. Für die fortgesetzte Nutzung beginnen die Lizenzen bei $749 und bieten verschiedene Optionen, um den Anforderungen Ihres Projekts zu entsprechen.

< PREVIOUS
In C# (Wie es für Entwickler funktioniert)
NÄCHSTES >
C# Unit Testing (Wie es für Entwickler funktioniert)

Sind Sie bereit, loszulegen? Version: 2024.10 gerade veröffentlicht

Gratis NuGet-Download Downloads insgesamt: 11,308,499 Lizenzen anzeigen >