Neu in .NET 9.0 [27]: Erweiterter Zugriff über Wrapper-Klassen
Auch bei Klassen mit generischen Parametern ist nun der Zugriff auf nicht öffentliche Mitglieder möglich.
(Bild: Pincasso/Shutterstock)
Lesezeit:
1 Min.
Von
- Dr. Holger Schwichtenberg
Der Zugriff auf nicht-öffentliche Mitglieder einer Klasse über eine Wrapper-Klasse ("Accessor"), die [UnsafeAccessorAttribute] nutzt, wurde in .NET 8.0 eingeführt.
Videos by heise
Nun funktioniert das auch mit generischen Parametern:
using System.Runtime.CompilerServices;
namespace NET9_Console.FCL90_UnsafeAccessor;
/// Der Zugriff auf nicht-öffentliche Mitglieder einer Klasse über eine Wrapper-Klasse, die [UnsafeAccessorAttribute] nutzt, wurde in .NET 8.0 eingeführt. Neu in .NET 9.0: Nun funktioniert dies auch mit generischen Parametern.
/// <summary>
/// Eine Klasse mit zwei privaten Mitgliedern, die wir über UnsafeAccessorAttribute von Außen nutzen wollen
/// </summary>
/// <typeparam name="T"></typeparam>
public class Printer<T>
{
private T _data = default;
private void Print<PreTextType>(PreTextType preText) { CUI.Green(preText.ToString()); Console.WriteLine(_data.ToString()); }
public override string ToString()
{
return "Data=" + (_data?.ToString() ?? "(leer)");
}
}
/// <summary>
/// Accessor für Printer<T>, um auf private Mitglieder zugreifen zu können
/// </summary>
class PrinterAccessor<T>
{
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_data")] // Zugriff auf das private Feld
public extern static ref T GetSetPrivateField(Printer<T> p);
[UnsafeAccessor(UnsafeAccessorKind.Method, Name = "Print")] // Zugriff auf die private Methode
public extern static void CallPrivatePrint<PreTextType>(Printer<T> p, PreTextType preText);
}
/// </summary>
class Client
{
public void Run()
{
CUI.Demo(nameof(FCL90_UnsafeAccessor));
CUI.H2("Erzeuge das Objekt mit den privaten Mitgliedern");
Printer<Consultant> printer = new Printer<Consultant>();
Console.WriteLine("Vorher:\n" + printer.ToString());
// Zugriff auf das Objekt via Accessor
CUI.H2("Setzen eines privaten Feldes");
ref Consultant data = ref PrinterAccessor<Consultant>.GetSetPrivateField(printer);
data = new Consultant() { ID = 42, FullName = "Dr. Holger Schwichtenberg", PersonalWebsite = "www.dotnet-doktor.de", Address = new Address() { City = "Essen" }, Languages = ["C#", "VB.NET", "JavaScript/TypeScript"] };
CUI.Success("Wert für Private Field gesetzt!");
Console.WriteLine("Kontrolle über Zugriff auf das öffentliche ToString():\n" + printer.ToString());
// Methode aufrufen
CUI.H2("Aufruf einer privaten Methode mit generischen Parametern: CallPrivatePrint<string>()");
PrinterAccessor<Consultant>.CallPrivatePrint<string>(printer, "Sie werden beraten von:");
}
}
Die Ausgabe des Listings zeigt den Zugriff über die Wrapper-Klasse.
(Bild: Screenshot (Holger Schwichtenberg))
(rme)