Freigeben über


Windows Forms-Zwischenablage und DataObject-Änderungen in .NET 10

In diesem Artikel erfahren Sie, wie Sie Ihre Windows Forms-Zwischenablage und Drag-and-Drop-Vorgänge auf die neuen typsicheren APIs in .NET 10 aktualisieren. Sie erfahren, wie Sie die neuen Clipboard.TryGetData und Clipboard.SetDataAsJson<T>(String, T) Methoden verwenden, verstehen, welche integrierten Typen ohne Änderungen funktionieren, und Strategien für die Behandlung von benutzerdefinierten Typen und Legacydaten nach dem Entfernen von BinaryFormatter.

BinaryFormatter wurde aufgrund von Sicherheitsrisiken aus der Laufzeit in .NET 9 entfernt. Diese Änderung hat die Zwischenablage- und Drag-and-Drop-Vorgänge mit benutzerdefinierten Objekten gestört. .NET 10 führt neue APIs ein, die JSON-Serialisierung und typsichere Methoden verwenden, um diese Funktionalität wiederherzustellen, die Sicherheit zu verbessern und eine bessere Fehlerbehandlung und prozessübergreifende Kompatibilität zu bieten.

Clipboard.SetData(String, Object) funktioniert nicht mehr mit benutzerdefinierten Typen, die BinaryFormatter für die Serialisierung erfordern. Diese Methode führt einen Kopiervorgang (standardmäßig) durch, der Daten sofort serialisiert, diese Serialisierung schlägt jedoch jetzt für Typen fehl, die BinaryFormatter benötigt werden, da sie entfernt wurden. Clipboard.GetData(String) ist in .NET 10 veraltet. Wenn BinaryFormatter für die Deserialisierung erforderlich ist, aber nicht aktiviert wurde, gibt GetData() eine NotSupportedException Instanz zurück. Verwenden Sie die neuen Clipboard.TryGetData und Clipboard.SetDataAsJson<T>(String, T) Methoden für typsichere Vorgänge und JSON-Serialisierung von benutzerdefinierten Objekten.

Die folgenden Abschnitte enthalten detaillierte Anleitungen zur Migration, erläutern, welche Typen ohne Änderungen funktionieren, und zeigen, wie sowohl neue Entwicklungs- als auch Legacydatenszenarien behandelt werden.

Voraussetzungen

Bevor Sie fortfahren, lesen Sie die folgenden Konzepte:

  • Wie Anwendungen BinaryFormatter in Zwischenablage- und Drag-and-Drop-Szenarien bis .NET 9 verwendet wurden.
  • Die Sicherheitslücken, die zur Entfernung von BinaryFormatter führten.
  • So arbeiten Sie mit System.Text.Json Serialisierungsmustern und deren Einschränkungen.

Weitere Informationen finden Sie in den folgenden Artikeln:

Entfernen von Änderungen von BinaryFormatter

Das BinaryFormatter Entfernen in .NET 9 ändert grundlegend, wie Windows Forms Zwischenablage- und Drag-and-Drop-Vorgänge mit benutzerdefinierten Typen verarbeitet. Diese Änderungen wirken sich auf vorhandene Codemuster aus und erfordern eine sorgfältige Migration zur Aufrechterhaltung der Funktionalität.

Benutzerdefinierte Typen serialisieren nicht mehr automatisch

In .NET 8 und früheren Versionen können Sie jedes serialisierbare benutzerdefinierte Objekt in der Zwischenablage platzieren, indem Sie die Datei aufrufen SetData(). Die BinaryFormatter behandelte die Serialisierung automatisch. Ab .NET 9 führt SetData() weiterhin einen Kopiervorgang aus, der Daten sofort serialisiert, aber diese Serialisierung schlägt für Typen fehl, die BinaryFormatter erfordern, weil BinaryFormatter entfernt wurde.

Der folgende Code funktioniert nicht mehr:

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static void BrokenCustomTypeExample()
{
    // This worked in .NET 8 and earlier but silently fails starting with .NET 9
    Person person = new Person { Name = "John", Age = 30 };
    Clipboard.SetData("MyApp.Person", person);  // No data is stored

    // Later attempts to retrieve the data return a NotSupportedException instance
    object data = Clipboard.GetData("MyApp.Person");
}
<Serializable>
Public Class Person
    Public Property Name As String
    Public Property Age As Integer
End Class

Public Shared Sub BrokenCustomTypeExample()
    ' This worked in .NET 8 and earlier but silently fails starting with .NET 9
    Dim person As New Person With {.Name = "John", .Age = 30}
    Clipboard.SetData("MyApp.Person", person)  ' No data is stored

    ' Later attempts to retrieve the data return a NotSupportedException instance
    Dim data As Object = Clipboard.GetData("MyApp.Person")
End Sub

Was Möglicherweise angezeigt wird

  • Die SetData() Methode wird abgeschlossen, ohne eine Ausnahme zu auslösen.
  • Die Daten werden in der Zwischenablage platziert, aber die Serialisierung schlägt bei Typen fehl, die BinaryFormatter benötigen.
  • Spätere Versuche, die Daten mit GetData() abzurufen, führen zu einer NotSupportedException-Instanz, die angibt, dass BinaryFormatter erforderlich, aber nicht aktiviert ist.

Migrationsleitfaden

Verwenden Sie die neue SetDataAsJson<T>() Methode, oder serialisieren Sie manuell auf ein string oder byte[]. Ausführliche Informationen finden Sie im Abschnitt "Arbeiten mit benutzerdefinierten Typen ".

GetData() ist veraltet - verwenden Sie stattdessen TryGetData<T>()

Die Legacymethode GetData() ist in .NET 10 veraltet. Diese Methode gibt in den meisten Fällen erfolgreich Daten zurück. Wenn jedoch BinaryFormatter für die Deserialisierung erforderlich ist und nicht aktiviert wurde, gibt GetData() eine Instanz zurück, die darauf hinweist, dass BinaryFormatter erforderlich ist. Sie sollten zu den neuen typsicheren TryGetData<T>() Methoden migrieren, um eine bessere Fehlerbehandlung und Typsicherheit zu gewährleisten.

Das folgende Beispiel zeigt das veraltete Muster, das Sie vermeiden sollten:

public static void ObsoleteGetDataExample()
{
    // Don't use - GetData() is obsolete in .NET 10
    object data = Clipboard.GetData("MyApp.Person");  // Obsolete method

    // Returns a NotSupportedException instance for a custom object type
    if (data is Person person)
    {
        Console.WriteLine($"Processing person: {person.Name}, Age: {person.Age}");
    }
}
Public Shared Sub ObsoleteGetDataExample()
    ' Don't use - GetData() is obsolete in .NET 10
    Dim data As Object = Clipboard.GetData("MyApp.Person")  ' Obsolete method

    ' Returns a NotSupportedException instance for a custom object type
    If TypeOf data Is Person Then
        Dim person As Person = DirectCast(data, Person)
        Console.WriteLine($"Processing person: {person.Name}, Age: {person.Age}")
    End If
End Sub

Verwenden Sie stattdessen den modernen typsicheren Ansatz mit TryGetData<T>():

public static void ModernTryGetDataExample()
{
    var data = new Person { Name = "Alice", Age = 28 };
    Clipboard.SetDataAsJson("MyAppData", data);

    // Use this - type-safe approach with TryGetData<T>()
    if (Clipboard.TryGetData("MyApp.Person", out Person person))
    {
        // person is guaranteed to be the correct type
        Console.WriteLine($"Processing person: {person.Name}, Age: {person.Age}");
    }
    else
    {
        // Handle the case where data isn't available or is the wrong type
        MessageBox.Show("Unable to retrieve person data from clipboard");
    }
}
Public Shared Sub ModernTryGetDataExample()
    Dim data As New Person With {.Name = "Alice", .Age = 30}
    Clipboard.SetDataAsJson("MyAppData", data)

    ' Use this - type-safe approach with TryGetData(Of T)()
    Dim person As Person = Nothing
    If Clipboard.TryGetData("MyApp.Person", person) Then
        ' person is guaranteed to be the correct type
        Console.WriteLine($"Processing person: {person.Name}, Age: {person.Age}")
    Else
        ' Handle the case where data isn't available or is the wrong type
        MessageBox.Show("Unable to retrieve person data from clipboard")
    End If
End Sub

Vorteile von TryGetData<T>()

  • Typsicherheit: Keine Umwandlung erforderlich – die Methode gibt den genauen Typ zurück, den Sie anfordern.
  • Klare Fehlerbehandlung: Gibt einen booleschen Erfolgsindikator zurück, anstatt null- oder Ausnahmemuster zu verwenden.
  • Zukunftssicher: Entwickelt für die Arbeit mit neuen Serialisierungsmethoden und Legacydatenunterstützung.

Identifizieren des betroffenen Codes

Suchen nach:

  • Alle GetData() Aufrufe, da die gesamte Methode unabhängig vom Datentyp veraltet ist.
  • DataObject.GetData() und IDataObject.GetData() Verwendung in Drag-and-Drop-Vorgängen.

Migrationsleitfaden

Ersetzen Sie alle GetData() Verwendungen durch typsichere TryGetData<T>() Methoden. Umfassende Beispiele für alle Überladungen finden Sie im Abschnitt " Neue typsichere APIs ".

Neue typsichere APIs

.NET 10 führt drei neue API-Familien ein, die Typsicherheit, bessere Fehlerbehandlung und JSON-Serialisierungsunterstützung für Zwischenablage- und Drag-and-Drop-Vorgänge bieten:

TryGetData<T>() -Methoden

Die TryGetData<T>() Familie ersetzt die veraltete GetData() Methode. Es bietet ein typensicheres Abrufen und eine klare Erfolg- oder Fehleranzeige für Ihre Zwischenablageoperationen.

Einfacher typsicherer Abruf

public static void BasicTypeSafeRetrievalExamples()
{
    // Retrieve text data using a standard format
    if (Clipboard.TryGetData(DataFormats.Text, out string textData))
        Console.WriteLine($"Text: {textData}");

    // Retrieve an integer using a custom format
    if (Clipboard.TryGetData("NumberData", out int numberData))
        Console.WriteLine($"Number: {numberData}");

    // Retrieve Unicode text using a standard format
    if (Clipboard.TryGetData(DataFormats.UnicodeText, out string unicodeText))
        Console.WriteLine($"Unicode: {unicodeText}");

    // Retrieve raw text data with OLE conversion control
    if (Clipboard.TryGetData(DataFormats.Text, out string rawText))
        Console.WriteLine($"Raw: {rawText}");

    // Retrieve file drops using a standard format
    if (Clipboard.TryGetData(DataFormats.FileDrop, out string[] files))
        Console.WriteLine($"Files: {string.Join(", ", files)}");
}
Public Shared Sub BasicTypeSafeRetrievalExamples()
    ' Retrieve text data using a standard format
    Dim textData As String = Nothing
    If Clipboard.TryGetData(DataFormats.Text, textData) Then
        Console.WriteLine($"Text: {textData}")
    End If

    ' Retrieve an integer using a custom format
    Dim numberData As Integer
    If Clipboard.TryGetData("NumberData", numberData) Then
        Console.WriteLine($"Number: {numberData}")
    End If

    ' Retrieve Unicode text using a standard format
    Dim unicodeText As String = Nothing
    If Clipboard.TryGetData(DataFormats.UnicodeText, unicodeText) Then
        Console.WriteLine($"Unicode: {unicodeText}")
    End If

    ' Retrieve raw text data with OLE conversion control
    Dim rawText As String = Nothing
    If Clipboard.TryGetData(DataFormats.Text, rawText) Then
        Console.WriteLine($"Raw: {rawText}")
    End If

    ' Retrieve file drops using a standard format
    Dim files As String() = Nothing
    If Clipboard.TryGetData(DataFormats.FileDrop, files) Then
        Console.WriteLine($"Files: {String.Join(", ", files)}")
    End If
End Sub

Benutzerdefinierte JSON-Typen

public static void CustomJsonTypesExamples()
{
    // Retrieve a custom type stored with SetDataAsJson<T>()
    if (Clipboard.TryGetData("Person", out Person person))
        Console.WriteLine($"Person: {person.Name}");

    // Retrieve application-specific data formats
    if (Clipboard.TryGetData("MyApp.Settings", out AppSettings settings))
        Console.WriteLine($"Settings: {settings.Theme}");

    // Retrieve complex custom objects
    if (Clipboard.TryGetData("DocumentData", out DocumentInfo doc))
        Console.WriteLine($"Document: {doc.Title}");
}
Public Shared Sub CustomJsonTypesExamples()
    ' Retrieve a custom type stored with SetDataAsJson(Of T)()
    Dim person As Person = Nothing
    If Clipboard.TryGetData("Person", person) Then
        Console.WriteLine($"Person: {person.Name}")
    End If

    ' Retrieve application-specific data formats
    Dim settings As AppSettings = Nothing
    If Clipboard.TryGetData("MyApp.Settings", settings) Then
        Console.WriteLine($"Settings: {settings.Theme}")
    End If

    ' Retrieve complex custom objects
    Dim doc As DocumentInfo = Nothing
    If Clipboard.TryGetData("DocumentData", doc) Then
        Console.WriteLine($"Document: {doc.Title}")
    End If
End Sub

SetDataAsJson<T>() -Methoden

Diese Methoden bieten eine automatische JSON-Serialisierung mit typsicherem Speicher durch System.Text.Json.

Angeben eines benutzerdefinierten Formats

public static void CustomFormatExample()
{
    var settings = new AppSettings { Theme = "Dark", AutoSave = true };

    // Use a custom format for better organization
    Clipboard.SetDataAsJson("MyApp.Settings", settings);
}
Public Shared Sub CustomFormatExample()
    Dim settings As New AppSettings With {.Theme = "Dark", .AutoSave = True}

    ' Use a custom format for better organization
    Clipboard.SetDataAsJson("MyApp.Settings", settings)
End Sub

Automatische Format-Ableitung

Durch Angeben des Typnamens als Datenformat TryGetData<T> kann das Format automatisch ableiten:

public static void AutomaticFormatInferenceExample()
{
    var person = new Person { Name = "Alice", Age = 25 };

    // Use the type name as the format
    Clipboard.SetDataAsJson(typeof(Person).FullName, person);

    // Retrieve the data and infer the format automatically
    if (Clipboard.TryGetData(out Person retrievedPerson))
    {
        Console.WriteLine($"Retrieved: {retrievedPerson.Name}");
    }
}
Public Shared Sub AutomaticFormatInferenceExample()
    Dim person As New Person With {.Name = "Alice", .Age = 25}

    ' Use the type name as the format
    Clipboard.SetDataAsJson(GetType(Person).FullName, person)

    ' Retrieve the data and infer the format automatically
    Dim retrievedPerson As Person = Nothing
    If Clipboard.TryGetData(retrievedPerson) Then
        Console.WriteLine($"Retrieved: {retrievedPerson.Name}")
    End If
End Sub

ITypedDataObject-Schnittstelle

Die Schnittstelle ermöglicht typsichere Drag & Drop-Vorgänge, indem sie mit typisierten Methoden erweitert.

Ab .NET 10 wird DataObject (ein allgemeiner Typ in Drag-and-Drop-Szenarien) ITypedDataObject implementieren.

Verwenden von ITypedDataObject in Drag-and-Drop-Szenarien

private void OnDragDrop(object sender, DragEventArgs e)
{
    if (e.Data is ITypedDataObject typedData)
    {
        // Retrieve files from drag data using a standard format
        if (typedData.TryGetData(DataFormats.FileDrop, out string[] files))
            Console.WriteLine($"Dropped files: {string.Join(", ", files)}");

        // Retrieve text using a standard format
        if (typedData.TryGetData(DataFormats.Text, out string text))
            Console.WriteLine($"Dropped text: {text}");

        // Retrieve custom items using an application-specific format
        if (typedData.TryGetData("CustomItem", out MyItem item))
            Console.WriteLine($"Dropped custom item: {item.Name} = {item.Value}");
    }
}
Private Sub OnDragDrop(sender As Object, e As DragEventArgs)
    If TypeOf e.Data Is ITypedDataObject Then
        Dim typedData As ITypedDataObject = CType(e.Data, ITypedDataObject)

        ' Retrieve files from drag data using a standard format
        Dim files As String() = Nothing
        If typedData.TryGetData(DataFormats.FileDrop, files) Then
            Console.WriteLine($"Dropped files: {String.Join(", ", files)}")
        End If

        ' Retrieve text using a standard format
        Dim text As String = Nothing
        If typedData.TryGetData(DataFormats.Text, text) Then
            Console.WriteLine($"Dropped text: {text}")
        End If

        ' Retrieve custom items using an application-specific format
        Dim item As MyItem = Nothing
        If typedData.TryGetData("CustomItem", item) Then
            Console.WriteLine($"Dropped custom item: {item.Name} = {item.Value}")
        End If
    End If
End Sub

Typen, die keine JSON-Serialisierung erfordern

Viele integrierte .NET-Typen funktionieren mit Zwischenablagevorgängen, ohne dass eine JSON-Serialisierung oder BinaryFormatter-Unterstützung erforderlich ist. Diese Typen serialisieren automatisch in das .NET Remoting Binary Format (NRBF), das eine effiziente Speicherung bietet und die Typsicherheit gewährleistet.

Diese Typen verwenden NRBF, dasselbe effiziente Binärformat, das von der Legacyversion BinaryFormatterverwendet wird. DIE NRBF-Serialisierung bietet die folgenden wichtigsten Vorteile:

  • Kompakte binäre Darstellung: Ermöglicht eine effiziente Speicherung und Übertragung.
  • Integrierte Typinformationen: Behält genaue .NET-Typen während Roundtrip-Vorgängen bei.
  • Prozessübergreifende Kompatibilität: Funktioniert zwischen verschiedenen .NET-Anwendungen.
  • Automatische Serialisierung: Typen serialisieren ohne benutzerdefinierten Code.

Hinweis

Methoden wie SetData() führen einen Kopiervorgang aus, der Daten sofort serialisiert und so sicherstellt, dass Zwischenablagedaten auch nach dem Beenden des aktuellen Prozesses beibehalten werden. Wenn Sie den DataObject Typ direkt mit SetDataObject(dataObject, copy)verwenden, können Sie steuern, wann die Serialisierung auftritt. Durch Festlegen des copy Parameters auf true (Standard) wird die sofortige Serialisierung erzwungen, während false die Serialisierung zurückverzögert wird, bis sie erforderlich ist. Wenn copy auf false festgelegt ist und die Daten im selben Prozess abgerufen werden, ist die Serialisierung möglicherweise nicht erforderlich, aber die Daten bleiben nach dem Beenden des Prozesses nicht erhalten.

Technische Details finden Sie in der .NET Remoting Binary Format-Spezifikation.

Klassen, die NRBF-codierte Daten unterstützen, werden im System.Formats.Nrbf Namespace implementiert.

Typsicherheitsgarantien

Windows Forms bietet mehrere Sicherheitsmechanismen für diese integrierten Typen:

  • Exakter Typabgleich. TryGetData gibt nur den angeforderten Typ zurück.
  • Automatische Überprüfung. Windows Forms überprüft während der Deserialisierung die Typkompatibilität.
  • Keine beliebige Codeausführung. Im Gegensatz zu benutzerdefinierten Typen mit BinaryFormatter können diese Typen keinen schädlichen Code ausführen.
  • Inhaltsüberprüfung erforderlich. Sie müssen weiterhin Dateninhalte und -bereiche für Ihre Anwendungslogik überprüfen.
  • Keine Größenbeschränkungen. Große Arrays oder Bitmaps sind nicht automatisch eingeschränkt. Überwachen sie die Speicherauslastung.

Unterstützte Grundtypen

Die folgenden Grundtypen funktionieren nahtlos mit Zwischenablage und DataObject Vorgängen. Sie benötigen keine benutzerdefinierte Serialisierung oder Konfiguration. Das Zwischenablagesystem behandelt diese integrierten .NET-Typen automatisch:

  • bool, byte, char, decimal, double, short, int und long.
  • sbyte, ushort, uint, ulong, float und string.
  • TimeSpan und DateTime.

Die folgenden Beispiele zeigen, wie diese Grundtypen direkt mit SetData() und TryGetData<T>() Methoden funktionieren:

public static void PrimitiveTypesExample()
{
    // Numeric types
    Clipboard.SetData("MyInt", 42);
    Clipboard.SetData("MyDouble", 3.14159);
    Clipboard.SetData("MyDecimal", 123.45m);

    // Text and character types
    Clipboard.SetData("MyString", "Hello World");
    Clipboard.SetData("MyChar", 'A');

    // Boolean and date/time types
    Clipboard.SetData("MyBool", true);
    Clipboard.SetData("MyDateTime", DateTime.Now);
    Clipboard.SetData("MyTimeSpan", TimeSpan.FromMinutes(30));

    // Later retrieval with type safety
    if (Clipboard.TryGetData("MyTimeSpan", out TimeSpan value))
    {
        Console.WriteLine($"Clipboard value is: {value}");
    }
}
Public Shared Sub PrimitiveTypesExample()
    ' Numeric types
    Clipboard.SetData("MyInt", 42)
    Clipboard.SetData("MyDouble", 3.14159)
    Clipboard.SetData("MyDecimal", 123.45D)

    ' Text and character types
    Clipboard.SetData("MyString", "Hello World")
    Clipboard.SetData("MyChar", "A"c)

    ' Boolean and date/time types
    Clipboard.SetData("MyBool", True)
    Clipboard.SetData("MyDateTime", DateTime.Now)
    Clipboard.SetData("MyTimeSpan", TimeSpan.FromMinutes(30))

    ' Later retrieval with type safety
    Dim value As TimeSpan

    If Clipboard.TryGetData("MyTimeSpan", value) Then
        Console.WriteLine($"Clipboard value is: {value}")
    End If
End Sub

Eine Sammlung primitiver Typen

Arrays und generische Listen unterstützter Grundtypen funktionieren ohne zusätzliche Konfiguration. Beachten Sie jedoch die folgenden Einschränkungen:

  • Alle Array- und Listenelemente müssen grundtyptypen unterstützt werden.
  • Vermeiden Sie string[] und List<string>, da das NRBF-Format die Verarbeitung von Nullwerten in Zeichenfolgenauflistungen komplex macht.
  • Speichern Sie Zeichenfolgen einzeln oder verwenden Sie die JSON-Serialisierung für Zeichenfolgensammlungen.

Die folgenden Beispiele zeigen, wie Arrays und Listen in der Zwischenablage festgelegt werden können:

public static void CollectionsExample()
{
    // Arrays of primitive types
    int[] numbers = { 1, 2, 3, 4, 5 };
    Clipboard.SetData("NumberArray", numbers);

    double[] coordinates = { 1.0, 2.5, 3.7 };
    Clipboard.SetData("Coordinates", coordinates);

    // Generic lists
    List<int> intList = new List<int> { 10, 20, 30 };
    Clipboard.SetData("IntList", intList);

    // Retrieval maintains type safety
    if (Clipboard.TryGetData("NumberArray", out int[] retrievedNumbers))
    {
        Console.WriteLine($"Numbers: {string.Join(", ", retrievedNumbers)}");
    }
}
Public Shared Sub CollectionsExample()
    ' Arrays of primitive types
    Dim numbers As Integer() = {1, 2, 3, 4, 5}
    Clipboard.SetData("NumberArray", numbers)

    Dim coordinates As Double() = {1.0, 2.5, 3.7}
    Clipboard.SetData("Coordinates", coordinates)

    ' Generic lists
    Dim intList As New List(Of Integer) From {10, 20, 30}
    Clipboard.SetData("IntList", intList)

    ' Retrieval maintains type safety
    Dim retrievedNumbers As Integer() = Nothing

    If Clipboard.TryGetData("NumberArray", retrievedNumbers) Then
        Console.WriteLine($"Numbers: {String.Join(", ", retrievedNumbers)}")
    End If
End Sub

System.Drawing-Typen

Allgemeine Grafiktypen aus dem System.Drawing Namespace funktionieren nahtlos mit Zwischenablage und DataObject Vorgängen. Diese Typen sind nützlich für Anwendungen, die mit visuellen Elementen arbeiten und zeichnungsbezogene Daten zwischen Komponenten oder Anwendungen übertragen müssen. Beachten Sie, dass die Serialisierung eines Bitmap eine große Menge an Arbeitsspeicher verbrauchen kann, insbesondere bei großen Bildern. Die folgenden Typen werden unterstützt:

  • Point, PointF, Rectangle, RectangleF.
  • Size, SizeF, Color.
  • Bitmap (kann bei Serialisierung erheblichen Speicher beanspruchen).

Die folgenden Beispiele zeigen, wie diese Grafikarten mit Zwischenablagevorgängen verwendet werden können.

public static void SystemDrawingTypesExample()
{
    // Geometric types
    Point location = new Point(100, 200);
    Rectangle bounds = new Rectangle(0, 0, 500, 300);
    Size dimensions = new Size(800, 600);

    Clipboard.SetData("Location", location);
    Clipboard.SetData("Bounds", bounds);
    Clipboard.SetData("Size", dimensions);

    // Color information
    Color backgroundColor = Color.FromArgb(255, 128, 64, 192);
    Clipboard.SetData("BackColor", backgroundColor);

    // Bitmap data (use with caution for large images)
    Bitmap smallIcon = new Bitmap(16, 16);
    Clipboard.SetData("Icon", smallIcon);
}
Public Shared Sub SystemDrawingTypesExample()
    ' Geometric types
    Dim location As New Point(100, 200)
    Dim bounds As New Rectangle(0, 0, 500, 300)
    Dim dimensions As New Size(800, 600)

    Clipboard.SetData("Location", location)
    Clipboard.SetData("Bounds", bounds)
    Clipboard.SetData("Size", dimensions)

    ' Color information
    Dim backgroundColor As Color = Color.FromArgb(255, 128, 64, 192)
    Clipboard.SetData("BackColor", backgroundColor)

    ' Bitmap data (use with caution for large images)
    Dim smallIcon As New Bitmap(16, 16)
    Clipboard.SetData("Icon", smallIcon)
End Sub

Arbeiten mit benutzerdefinierten Typen

Wenn Sie SetDataAsJson<T>(String, T) und TryGetData mit benutzerdefinierten Typen verwenden, behandelt System.Text.Json die Serialisierung automatisch. Viele Typen funktionieren ohne spezielle Konfiguration – Datensätze, einfache Klassen und Strukturen mit öffentlichen Eigenschaften serialisieren nahtlos.

Einfache Typen, die ohne Attribute funktionieren

Die einfachsten benutzerdefinierten Typen erfordern keine spezielle Konfiguration:

// Records work without any attributes.
public record PersonInfo(string Name, int Age, string Email);

// Simple classes serialize all public properties automatically.
public class DocumentMetadata
{
    public string Title { get; set; }
    public DateTime Created { get; set; }
    public string Author { get; set; }
}

// Structs with public properties work seamlessly.
public struct Point3D
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
}
' Simple classes serialize all public properties automatically.
Public Class DocumentMetadata
    Public Property Title As String
    Public Property Created As DateTime
    Public Property Author As String
End Class

' Structs with public properties work seamlessly.
Public Structure Point3D
    Public Property X As Double
    Public Property Y As Double
    Public Property Z As Double
End Structure

Verwenden von JSON-Attributen für erweiterte Steuerelemente

Verwenden Sie System.Text.Json Attribute nur, wenn Sie das Serialisierungsverhalten anpassen müssen. Umfassende Anleitungen zur System.Text.Json Serialisierung, Attributen und erweiterten Konfigurationsoptionen finden Sie unter JSON-Serialisierung und Deserialisierung in .NET.

Das folgende Beispiel zeigt, wie Sie JSON-Attribute verwenden können, um die Serialisierung zu steuern:

public class ClipboardFriendlyType
{
    // Include a field that normally isn't serialized
    [JsonInclude]
    private int _privateData;

    // Public properties are always serialized
    public string Name { get; set; }
    
    // Exclude sensitive or non-essential data
    [JsonIgnore]
    public string InternalId { get; set; }
    
    // Handle property name differences for compatibility
    [JsonPropertyName("display_text")]
    public string DisplayText { get; set; }
    
    // Control null value handling
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string OptionalField { get; set; }
}
Public Class ClipboardFriendlyType
    ' Include a field that normally isn't serialized
    <JsonInclude>
    Private _privateData As Integer

    ' Public properties are always serialized
    Public Property Name As String

    ' Exclude sensitive or non-essential data
    <JsonIgnore>
    Public Property InternalId As String

    ' Handle property name differences for compatibility
    <JsonPropertyName("display_text")>
    Public Property DisplayText As String

    ' Control null value handling
    <JsonIgnore(Condition:=JsonIgnoreCondition.WhenWritingNull)>
    Public Property OptionalField As String
End Class

Example: Zwischenablagevorgänge mit benutzerdefinierten Typen

public static void CustomTypesClipboardOperationsExample()
{
    var data = new ClipboardFriendlyType 
    { 
        Name = "Sample", 
        DisplayText = "Sample Display Text",
        InternalId = "internal-123" // This property isn't serialized due to [JsonIgnore]
    };

    Clipboard.SetDataAsJson("MyAppData", data);

    if (Clipboard.TryGetData("MyAppData", out ClipboardFriendlyType retrieved))
    {
        Console.WriteLine($"Retrieved: {retrieved.Name}");
        // retrieved.InternalId is null because of [JsonIgnore]
    }
}
Public Shared Sub CustomTypesClipboardOperationsExample()
    Dim data As New ClipboardFriendlyType With {
        .Name = "Sample",
        .DisplayText = "Sample Display Text",
        .InternalId = "internal-123" ' This property isn't serialized due to <JsonIgnore>
    }

    Clipboard.SetDataAsJson("MyAppData", data)

    Dim retrieved As ClipboardFriendlyType = Nothing
    If Clipboard.TryGetData("MyAppData", retrieved) Then
        Console.WriteLine($"Retrieved: {retrieved.Name}")
        ' retrieved.InternalId is null because of <JsonIgnore>
    End If
End Sub

Vorsicht

BinaryFormatter Unterstützung wird nicht empfohlen. Verwenden Sie sie nur als temporäre Migrationsbrücke für Ältere Anwendungen, die nicht sofort zu den neuen typsicheren APIs migrieren können.

Um die Verwendung von BinaryFormatter für Zwischenablagevorgänge in .NET 10 fortzusetzen, können Sie eine eingeschränkte Unterstützung durch eine explizite Konfiguration aktivieren. Dieser Ansatz birgt erhebliche Sicherheitsrisiken und erfordert mehrere Schritte.

Vollständige schrittweise Anleitungen finden Sie unter Aktivieren der BinaryFormatter-Zwischenablageunterstützung (nicht empfohlen). Allgemeine Anleitungen zur Migration finden Sie im BinaryFormatter-Migrationshandbuch.

Sicherheitswarnungen und Risiken

BinaryFormatter ist aus folgenden Gründen unsicher und veraltet:

  • Sicherheitsanfälligkeiten bezüglich beliebiger Codeausführung: Angreifer können während der Deserialisierung bösartigen Code ausführen und Ihre Anwendung Remoteangriffen offenlegen.
  • Denial of Service-Angriffe: Böswillige Zwischenablagedaten können übermäßigen Arbeitsspeicher oder CPU-Ressourcen verbrauchen, was Abstürze oder Instabilität verursacht.
  • Informationsveröffentlichungsrisiken: Angreifer extrahieren möglicherweise vertrauliche Daten aus dem Arbeitsspeicher.
  • Keine Sicherheitsgrenzen: Das Format ist grundsätzlich unsicher, und Konfigurationseinstellungen können es nicht schützen.

Aktivieren Sie diese Unterstützung nur als temporäre Brücke, während Sie Ihre Anwendung so aktualisieren, dass sie die neuen typsicheren APIs verwendet.

Ausführliche Sicherheitsrichtlinien und Konfigurationsschritte finden Sie in der Anleitung zu Sicherheitswarnungen und Risiken .

Implementierung von sicherheitsorientierten Typenauflösungen

Selbst bei aktiviertem BinaryFormatter müssen Sie Typauflöser implementieren, um die Deserialisierung auf explizit genehmigte Typen zu beschränken. Befolgen Sie die folgenden Richtlinien:

  • Verwenden Sie explizite Zulassungslisten. Ablehnen eines Typs, der nicht explizit genehmigt wurde.
  • Typnamen überprüfen. Stellen Sie sicher, dass Typnamen exakt den erwarteten Werten entsprechen.
  • Beschränken Sie sich auf wesentliche Typen. Schließen Sie nur Typen ein, die für die Funktionalität der Zwischenablage erforderlich sind.
  • Ausnahmen für unbekannte Typen auslösen. Nicht autorisierte Typen eindeutig ablehnen.
  • Regelmäßig überprüfen. Prüfen und aktualisieren Sie die Erlaubt-Liste nach Bedarf.

Vollständige Implementierungsbeispiele und Codebeispiele finden Sie in der Anleitung zum Implementieren sicherheitsorientierter Typenlöser .

Mit KI Clipboard-Code migrieren

Das Migrieren von Zwischenablagevorgängen von .NET 8 zu .NET 10 umfasst systematische Codeänderungen in mehreren Dateien und Klassen. KI-Tools wie GitHub Copilot können Dazu beitragen, Ihre Migration zu beschleunigen, indem legacymuster identifiziert, moderne Ersetzungen vorgeschlagen und Testszenarien erstellt werden. Anstatt Ihre Codebasis manuell zu durchsuchen und jeden Zwischenablagevorgang einzeln zu konvertieren, können Sie KI verwenden, um sich wiederholende Aufgaben zu bearbeiten und sich dabei auf die Überprüfung von Ergebnissen und die Behandlung von Randfällen zu konzentrieren.

Die folgenden Abschnitte zeigen spezifische Eingabeaufforderungsstrategien für verschiedene Aspekte der Zwischenablagemigration, von der Suche nach problematischen Codemustern bis hin zum Erstellen robuster JSON-serialisierbarer Typen und umfassender Testsammlungen.

Verwendung von KI zur Identifizierung von veralteten Zwischenablagemustern

Verwenden Sie Copilot, um Ihre Codebasis zu scannen und Zwischenablagevorgänge zu finden, die eine Migration benötigen. Auf diese Weise können Sie den Umfang der erforderlichen Änderungen verstehen, bevor Sie die eigentliche Migration starten.

Find all clipboard operations in my codebase that use GetData(), SetData() with custom objects, DataObject.GetData(), or IDataObject.GetData(). Show me the file paths and line numbers where these patterns occur.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

KI verwenden, um GetData() in TryGetData<T>() zu konvertieren.

Verwenden Sie Copilot, um veraltete GetData() Aufrufe in das neue typsichere TryGetData<T>() Muster zu konvertieren. Diese Konvertierung umfasst eine ordnungsgemäße Fehlerbehandlung und beseitigt unsichere Umwandlungen.

Convert this GetData() clipboard code to use the new TryGetData<T>() method with proper error handling:

[paste your existing GetData() code here]

Make sure to eliminate casting and add appropriate error handling for when the data isn't available.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

Verwenden Sie KI, um SetData() nach SetDataAsJson<T>() zu migrieren.

Verwenden Sie Copilot, um benutzerdefinierte Objektspeicher aus der veralteten SetData() Methode in den neuen SetDataAsJson<T>() Ansatz zu konvertieren. Dadurch wird sichergestellt, dass Ihre benutzerdefinierten Objekte ordnungsgemäß in die Zwischenablage serialisiert werden.

Take this SetData() clipboard code that stores custom objects:

[paste your existing SetData() code here]

Convert it to use SetDataAsJson<T>() and make the custom types JSON-serializable. Add any necessary System.Text.Json attributes if the types have complex properties.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

Verwenden von KI zum Erstellen von JSON-serialisierbaren Datenmodellen

Verwenden Sie Copilot, um benutzerdefinierte Typen zu entwerfen, die nahtlos mit SetDataAsJson<T>() und TryGetData<T>(). Dies schließt das Hinzufügen geeigneter Attribute für Eigenschaften ein, die eine spezielle Behandlung erfordern.

Create a JSON-serializable version of this class for clipboard operations:

[paste your existing class definition here]

Make it work with System.Text.Json, add JsonIgnore for sensitive properties, JsonInclude for private fields that should serialize, and JsonPropertyName for any properties that need different names in JSON.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

Verwenden Sie KI, um typsichere Wrapper-Methoden zu generieren

Verwenden Sie Copilot, um Wrappermethoden zu erstellen, die die neuen Zwischenablage-APIs kapseln und saubere Schnittstellen für die spezifischen Datentypen Ihrer Anwendung bereitstellen.

Create a type-safe clipboard wrapper class that provides methods for storing and retrieving these custom types:

[list your custom types here]

Use SetDataAsJson<T>() and TryGetData<T>() internally, include proper error handling, and add methods like SavePersonToClipboard() and TryGetPersonFromClipboard().

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

Verwenden von KI zum Erstellen umfassender Tests

Verwenden Sie Copilot, um Testsuiten zu generieren, die überprüfen, ob die Migration der Zwischenablage ordnungsgemäß funktioniert, einschließlich Roundtrip-Serialisierungstests und Fehlerbehandlungsszenarien.

Generate comprehensive unit tests for this clipboard code:

[paste your migrated clipboard code here]

Include tests for successful round-trip serialization, handling of null values, error cases when data isn't available, and verification that the migrated code produces the same results as the original for valid scenarios.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.

Verwenden von KI zum Überprüfen von Migrationsergebnissen

Verwenden Sie Copilot, um Ihren migrierten Code zu überprüfen und potenzielle Probleme oder Bereiche zu identifizieren, in denen die Migration möglicherweise nicht abgeschlossen ist.

Review this migrated clipboard code for potential issues:

[paste your migrated code here]

Check for: missing error handling, types that might not serialize properly to JSON, performance concerns with large objects, security issues, and any remaining uses of obsolete methods.

Copilot wird von KI unterstützt, so dass Überraschungen und Fehler möglich sind. Weitere Informationen finden Sie in den häufig gestellten Fragen zur allgemeinen Verwendung von Copilot.