Zum Inhalt springen

C# CSharp Programmierung fortgeschrittene Techniken – Von Variablen zu Azure Cloud Techniken.

C# Charp Programmierung Tutorial

Werbung: Wenn Du ein gutes C# Lern-Buch benötigst, können wir Dir folgendes Buch von Amazon.de empfehlen:

Inhaltsverzeichnis

31. Interoperabilität mit nativen Bibliotheken (P/Invoke)

In einigen Fällen möchtest du möglicherweise auf nativen Code zugreifen, der in Sprachen wie C oder C++ geschrieben wurde. C# bietet dafür P/Invoke (Platform Invocation), eine Möglichkeit, Funktionen aus nativen DLLs in deinen C#-Code zu integrieren.

Ein Beispiel für P/Invoke:

 using System.Runtime.InteropServices;

class Beispiel
{
// Deklaration einer externen Funktion aus der Windows API (kernel32.dll)
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void Beep(uint dwFreq, uint dwDuration);

public void BeepAufrufen()
{
Beep(750, 300); // Erzeugt einen Piepton mit 750 Hz für 300 ms
}
}

In diesem Beispiel wird die Beep-Funktion aus der Windows-API verwendet. Mit [DllImport] kannst du auf viele native Funktionen zugreifen, die außerhalb des .NET-Frameworks liegen. Dies ist besonders nützlich, wenn du mit Legacy-Systemen oder spezialisierten nativen Bibliotheken arbeiten musst.

32. Marshalling

Wenn du mit P/Invoke arbeitest, musst du oft Marshalling verwenden, um Daten zwischen dem .NET-Managed-Code und dem nativen Unmanaged-Code korrekt zu übertragen. Marshalling sorgt dafür, dass komplexe Datentypen wie Strukturen, Arrays und Strings richtig zwischen den unterschiedlichen Speicherumgebungen konvertiert werden.

Beispiel:

 [StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
public int Zahl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Text;
}

[DllImport("example.dll")]
public static extern void FunktionMitStruktur(MyStruct daten);

Hier wird MarshalAs verwendet, um den String korrekt von .NET nach Unmanaged-Code zu übertragen.

33. Unit Testing und Teststrategien in C#

C# bietet umfangreiche Unterstützung für Unit Testing durch Bibliotheken wie xUnit, NUnit und MSTest. Unit Testing hilft dir, einzelne Einheiten deines Codes, wie Methoden oder Klassen, zu testen, um sicherzustellen, dass sie korrekt funktionieren.

Beispiel für einen einfachen Unit Test mit xUnit:

 using Xunit;

public class MatheTests
{
[Fact]
public void Addiere_ZweiZahlen_ReturnsErgebnis()
{
// Arrange
int zahl1 = 2;
int zahl2 = 3;

// Act
int ergebnis = Addiere(zahl1, zahl2);

// Assert
Assert.Equal(5, ergebnis);
}

public int Addiere(int a, int b)
{
return a + b;
}
}
  • Arrange: Bereite die Daten vor.
  • Act: Führe die Methode oder Aktion aus.
  • Assert: Überprüfe, ob das Ergebnis korrekt ist.

Mocking

In Unit Tests möchtest du oft Teile deines Codes isolieren und Abhängigkeiten „mocken“ (simulieren). Hierzu wird oft die Bibliothek Moq verwendet.

Beispiel für einen Mock-Test:

 using Moq;
using Xunit;

public interface IDatenbank
{
string HoleDaten();
}

public class Service
{
private readonly IDatenbank _datenbank;

public Service(IDatenbank datenbank)
{
_datenbank = datenbank;
}

public string VerarbeiteDaten()
{
string daten = _datenbank.HoleDaten();
return daten.ToUpper();
}
}

public class ServiceTests
{
[Fact]
public void VerarbeiteDaten_RuftDatenVonDatenbankAb()
{
// Arrange
var mockDatenbank = new Mock<IDatenbank>();
mockDatenbank.Setup(db => db.HoleDaten()).Returns("testdaten");

Service service = new Service(mockDatenbank.Object);

// Act
string ergebnis = service.VerarbeiteDaten();

// Assert
Assert.Equal("TESTDATEN", ergebnis);
}
}

Hier wird ein Mock-Objekt von der IDatenbank-Schnittstelle erstellt, um sicherzustellen, dass der Test isoliert bleibt und nicht auf eine echte Datenbank zugreift.

34. Benchmarking und Performanceoptimierung in C#

Die Performance eines Programms ist oft entscheidend, insbesondere bei Anwendungen, die große Datenmengen verarbeiten oder zeitkritisch sind. Es gibt mehrere Techniken, um die Leistung deines Codes zu analysieren und zu verbessern.

BenchmarkDotNet

Eine der besten Möglichkeiten, die Performance deines C#-Codes zu testen, ist die Verwendung von BenchmarkDotNet, einer Bibliothek zum Messen und Vergleichen der Performance verschiedener Codeabschnitte.

C# Beispiel:

 using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

public class BenchmarkBeispiel
{
[Benchmark]
public void SchleifenBenchmark()
{
for (int i = 0; i < 1000; i++)
{
// Simuliere Arbeit
}
}
}

public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<BenchmarkBeispiel>();
}
}

In diesem Beispiel misst BenchmarkDotNet die Zeit, die für das Ausführen der Schleife benötigt wird, und gibt detaillierte Performance-Berichte aus.

Optimierung mit Span<T> und Memory<T>

Wie bereits erwähnt, kann die Verwendung von Span<T> und Memory<T> erheblich zur Optimierung des Speichermanagements beitragen, insbesondere wenn du mit großen Datenmengen arbeitest, ohne Kopien zu erstellen oder unnötige Zuweisungen zu erzeugen.

Beispiel:

 public void VerarbeiteDaten(Span<int> daten)
{
for (int i = 0; i < daten.Length; i++)
{
daten[i] *= 2;
}
}

Hier wird Span<int> verwendet, um Daten direkt im Speicher zu verarbeiten, ohne zusätzlichen Overhead.

35. Aspektorientierte Programmierung (AOP)

Aspektorientierte Programmierung ermöglicht es, Querfeldeins-Logik (Cross-Cutting Concerns) wie Logging, Sicherheit oder Transaktionsmanagement von der eigentlichen Geschäftslogik zu trennen. In C# wird AOP oft durch PostSharp oder Fody implementiert.

Ein einfaches Beispiel für Logging mit AOP:

 [LogAspect]
public void WichtigeMethode()
{
Console.WriteLine("Wichtige Methode wird ausgeführt.");
}

// Der Aspekt, der das Logging übernimmt
[Serializable]
public class LogAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine($"Aufruf von {args.Method.Name} gestartet.");
}

public override void OnExit(MethodExecutionArgs args)
{
Console.WriteLine($"Aufruf von {args.Method.Name} beendet.");
}
}

In diesem Beispiel wird der Aspekt LogAspect verwendet, um automatisch Logging hinzuzufügen, wenn die Methode aufgerufen wird.

36. Source Generators

Source Generators sind eine neuere Ergänzung in C#, die es dir ermöglicht, zur Compilezeit zusätzlichen Code zu generieren. Das kann nützlich sein, um Boilerplate-Code zu vermeiden und automatisch effizienten, spezifischen Code zu erstellen.

Beispiel für einen einfachen Source Generator:

 using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using System.Text;

[Generator]
public class HalloWeltGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var source = @"
namespace HalloWelt
{
public static class GenerierteKlasse
{
public static void SagHallo()
{
System.Console.WriteLine(""Hallo, Welt!"");
}
}
}";

context.AddSource("GenerierteKlasse.g.cs", SourceText.From(source, Encoding.UTF8));
}

public void Initialize(GeneratorInitializationContext context) { }
}

Dieser Generator fügt während der Compilezeit eine neue Klasse GenerierteKlasse hinzu, die eine Methode SagHallo enthält.

37. C# und Cloud-Entwicklung

In der modernen Softwareentwicklung ist die Cloud ein zentrales Thema. C# spielt eine wichtige Rolle bei der Entwicklung von Cloud-basierten Anwendungen, insbesondere im .NET-Ökosystem.

Azure SDK

Das Azure SDK bietet dir Zugriff auf viele Azure-Dienste wie Speicher, Datenbanken, Messaging und mehr. Ein Beispiel für die Verwendung des Azure Blob Storage:

 using Azure.Storage.Blobs;

public async Task HochladenZuBlobStorage(string verbindungsString, string containerName, string dateiPfad)
{
BlobServiceClient blobServiceClient = new BlobServiceClient(verbindungsString);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
BlobClient blobClient = containerClient.GetBlobClient(Path.GetFileName(dateiPfad));

await blobClient.UploadAsync(date

37. C# und Cloud-Entwicklung (Fortsetzung)

Die Cloud-Entwicklung mit C# ermöglicht es, leistungsstarke Anwendungen zu erstellen, die auf skalierbare und verteilte Weise in der Cloud laufen. Wie schon erwähnt, spielt Microsoft Azure eine Schlüsselrolle, und wir können eine Vielzahl von Diensten in der Azure-Umgebung nutzen, um verschiedene Anwendungen zu hosten, wie z.B. Web-Apps, Serverless Functions, Datenbanken und mehr.

Hochladen zu Azure Blob Storage (Fortsetzung):

 using Azure.Storage.Blobs;

public async Task HochladenZuBlobStorage(string verbindungsString, string containerName, string dateiPfad)
{
BlobServiceClient blobServiceClient = new BlobServiceClient(verbindungsString);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
BlobClient blobClient = containerClient.GetBlobClient(Path.GetFileName(dateiPfad));

// Datei zum Blob Storage hochladen
await blobClient.UploadAsync(dateiPfad, true);

Console.WriteLine("Datei erfolgreich hochgeladen.");
}

Dieser Code zeigt, wie du mithilfe des Azure Storage SDK Dateien in Azure Blob Storage hochladen kannst. Dies ist besonders nützlich für Anwendungen, die große Mengen an Dateien speichern müssen, wie z.B. Bilder, Videos oder Backups.

Azure Functions mit C#

Azure Functions ermöglichen es dir, serverlose Funktionen zu erstellen, die auf bestimmte Ereignisse reagieren, z.B. HTTP-Anfragen, Datenbankänderungen oder Nachrichten in Warteschlangen.

Beispiel für eine Azure Function in C#:

 using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

public static class HelloWorldFunction
{
[FunctionName("HelloWorld")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("HelloWorld Function wurde aufgerufen.");

return new OkObjectResult("Hallo, Azure Functions!");
}
}

Diese Funktion reagiert auf HTTP-Anfragen und gibt eine einfache Nachricht zurück. Azure Functions sind besonders nützlich für die Implementierung von Microservices oder kleinen, leichtgewichtigen Aufgaben.

38. C# und Microservices

C# ist ideal geeignet für die Entwicklung von Microservices, einem Architekturansatz, bei dem eine Anwendung aus einer Sammlung kleiner, lose gekoppelter Dienste besteht, die unabhängig voneinander bereitgestellt und skaliert werden können.

In der .NET-Welt ist ASP.NET Core das Framework der Wahl für die Erstellung von Microservices. Es bietet Funktionen wie Dependency Injection, Middleware und einfache Integration in Cloud-Dienste.

Beispiel: Einfacher Microservice in ASP.NET Core

 using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();

app.MapGet("/", () => "Willkommen bei meinem Microservice!");
app.MapControllers();
app.Run();

Hier wird ein minimaler Microservice erstellt, der HTTP-Anfragen verarbeitet. In einer echten Anwendung würdest du mehrere Endpunkte hinzufügen, um verschiedene Funktionen deines Services bereitzustellen. Du kannst auch Docker verwenden, um diese Microservices zu containerisieren und in der Cloud bereitzustellen.

39. Docker und C#

Docker ist ein großartiges Tool, um Anwendungen in Containern zu isolieren und bereitzustellen. C#-Anwendungen, insbesondere solche, die in der Cloud oder in einer Microservice-Architektur ausgeführt werden, können von der Verwendung von Docker profitieren.

Dockerfile für eine ASP.NET Core-Anwendung

Ein einfaches Dockerfile, um eine ASP.NET Core-Anwendung zu containerisieren:

 # Verwende das offizielle .NET SDK-Image, um das Projekt zu bauen
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /out

# Verwende das Runtime-Image für die Ausführung der Anwendung
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime
WORKDIR /app
COPY --from=build /out .
ENTRYPOINT ["dotnet", "MeineApp.dll"]

Dieses Dockerfile baut die Anwendung und erstellt dann einen Container, der die .NET Runtime verwendet, um die Anwendung auszuführen. Docker macht es einfach, die Anwendung auf verschiedene Umgebungen zu übertragen und sicherzustellen, dass sie überall gleich läuft.

40. Event-Driven Architecture mit C#

In einer Event-Driven Architecture reagieren Dienste auf Ereignisse, die von anderen Diensten oder Systemen ausgelöst werden. In der .NET-Welt kannst du dies mit Technologien wie Azure Event Grid, Azure Service Bus oder RabbitMQ umsetzen.

Beispiel mit Azure Service Bus

Mit Azure Service Bus kannst du Nachrichten zwischen verschiedenen Microservices austauschen. Hier ist ein einfaches Beispiel für das Senden und Empfangen von Nachrichten:

 using Azure.Messaging.ServiceBus;

string connectionString = "<Dein Service Bus Verbindungsstring>";
string queueName = "<Dein Warteschlangenname>";

// Senden einer Nachricht
ServiceBusClient client = new ServiceBusClient(connectionString);
ServiceBusSender sender = client.CreateSender(queueName);

await sender.SendMessageAsync(new ServiceBusMessage("Hallo, Welt!"));
Console.WriteLine("Nachricht gesendet.");

// Empfangen einer Nachricht
ServiceBusProcessor processor = client.CreateProcessor(queueName);

processor.ProcessMessageAsync += async (ProcessMessageEventArgs args) =>
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Nachricht empfangen: {body}");
await args.CompleteMessageAsync(args.Message);
};

await processor.StartProcessingAsync();

In diesem Beispiel wird eine Nachricht in eine Service Bus-Warteschlange gesendet und anschließend von einem Empfänger verarbeitet.

Seiten: 1 2 3 4 5 6