Windows Forms urklipp och DataObject-ändringar i .NET 10

I den här artikeln får du lära dig hur du uppgraderar dina klipp- och dra-och-släpp-operationer i Windows Forms till de nya typsäkra API:erna i .NET 10. Du får lära dig att använda de nya Clipboard.TryGetData metoderna och Clipboard.SetDataAsJson<T>(String, T) metoderna, förstå vilka inbyggda typer som fungerar utan ändringar och identifiera strategier för hantering av anpassade typer och äldre data efter borttagningen av BinaryFormatter.

BinaryFormatter togs bort från körningen i .NET 9 på grund av säkerhetsrisker. Den här ändringen bröt urklipps- och dra-och-släpp-operationer med anpassade objekt. .NET 10 introducerar nya API:er som använder JSON-serialisering och typsäkra metoder för att återställa den här funktionen, förbättra säkerheten och ge bättre felhantering och kompatibilitet mellan processer.

Clipboard.SetData(String, Object) fungerar inte längre med anpassade typer som kräver BinaryFormatter för att serialiseras. Den här metoden utför en kopieringsåtgärd (som standard) som serialiserar data omedelbart, men serialiseringen misslyckas nu för typer som behöver BinaryFormatter eftersom den har tagits bort. Clipboard.GetData(String) är föråldrad i .NET 10. När BinaryFormatter krävs för deserialisering men inte är aktiverat returnerar GetData() en NotSupportedException instans. Använd de nya Clipboard.TryGetData metoderna och Clipboard.SetDataAsJson<T>(String, T) för typsäkra åtgärder och JSON-serialisering av anpassade objekt.

Följande avsnitt innehåller detaljerad migreringsvägledning, förklarar vilka typer som fungerar utan ändringar och visar hur du hanterar både nya utvecklingsscenarier och äldre datascenarier.

Förutsättningar

Innan du fortsätter bör du gå igenom följande begrepp:

  • Hur applikationer använde BinaryFormatter i urklipp och situationer för dra och släpp före .NET 9.
  • Säkerhetsproblemen som ledde till borttagningen av BinaryFormatter.
  • Så här arbetar du med System.Text.Json serialiseringsmönster och deras begränsningar.

Mer information finns i följande artiklar:

Kritiska ändringar från borttagning av BinaryFormatter

Om du tar bort BinaryFormatter i .NET 9 ändras i grunden hur Windows Forms hanterar Urklipp och dra och släpp-åtgärder med anpassade typer. Dessa ändringar påverkar befintliga kodmönster och kräver noggrann migrering för att underhålla funktioner.

Anpassade typer serialiseras inte längre automatiskt

I .NET 8 och tidigare kan du placera vilket serialiserbart anpassat objekt som helst i Urklipp genom att anropa SetData(). Den BinaryFormatter hanterade serialiseringen automatiskt. Från och med .NET 9 SetData() utför fortfarande en kopieringsåtgärd som serialiserar data omedelbart, men den här serialiseringen misslyckas för typer som kräver BinaryFormatter eftersom den har tagits bort.

Följande kod fungerar inte längre:

[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

Det här kan du se

  • Metoden SetData() slutförs utan att utlösa ett undantag.
  • Data placeras på urklipp, men serialiseringen misslyckas för typer som kräver BinaryFormatter.
  • Senare försök att hämta data med GetData() gör att NotSupportedException returnerar en instans som anger att BinaryFormatter är nödvändigt men inte aktiverat.

Migreringsvägledning

Använd den nya SetDataAsJson<T>() metoden eller serialisera manuellt till en string eller byte[]. Mer information finns i avsnittet Arbeta med anpassade typer .

GetData() är föråldrad – använd TryGetData<T>() i stället

Den äldre GetData() metoden är föråldrad i .NET 10. Den här metoden returnerar data i de flesta fall, men när BinaryFormatter krävs för deserialisering och inte är aktiverad, returnerar GetData() en NotSupportedException-instans som anger att BinaryFormatter behövs. Du bör migrera till de nya typsäkra TryGetData<T>() metoderna för bättre felhantering och typsäkerhet.

I följande exempel visas det föråldrade mönster som du bör undvika:

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

Använd i stället den moderna typsäkra metoden med 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

Fördelar med TryGetData<T>()

  • Typsäkerhet: Inget behov av gjutning – metoden returnerar den exakta typ som du begär.
  • Rensa felhantering: Returnerar en boolesk framgångsindikator i stället för att använda null- eller undantagsmönster.
  • Framtidssäker: Utformad för att fungera med nya serialiseringsmetoder och äldre datastöd.

Så här identifierar du påverkad kod

Sök efter:

  • Alla GetData() anrop, eftersom hela metoden är föråldrad oavsett datatyp.
  • DataObject.GetData() och IDataObject.GetData() användning i drag-och-släpp-operationer.

Migreringsvägledning

Ersätt all användning av GetData() med typsäkra TryGetData<T>()-metoder. Omfattande exempel på alla överlagringar finns i avsnittet Nya typsäkra API:er .

Nya typsäkra API:er

.NET 10 introducerar tre nya API-familjer som ger typsäkerhet, bättre felhantering och JSON-serialiseringsstöd för Urklipps- och dra-och-släpp-åtgärder:

TryGetData<T>()-metoder

Familjen TryGetData<T>() ersätter den föråldrade GetData() metoden. Det ger typsäker hämtning och tydlig indikation på framgång eller misslyckande för dina urklippsåtgärder.

Grundläggande typsäker hämtning

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

Anpassade JSON-typer

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>()-metoder

Dessa metoder ger automatisk JSON-serialisering för System.Text.Json med typsäker lagring.

Ange ett anpassat format

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

Automatisk formatinferens

Genom att ange typnamnet som dataformat TryGetData<T> kan du härleda formatet automatiskt:

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-gränssnitt

Gränssnittet ITypedDataObject möjliggör typsäkra dra-och-släpp-åtgärder genom att utöka IDataObject med metoder som är typade.

Från och med .NET 10 implementerar DataObject (en vanlig typ i dra-och-släpp-scenarier) ITypedDataObject.

Använda ITypedDataObject i dra och släpp-scenarier

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

Typer som inte kräver JSON-serialisering

Många inbyggda .NET-typer fungerar med Urklippsåtgärder utan att JSON-serialisering eller BinaryFormatter stöd krävs. Dessa typer serialiseras automatiskt till .NET Remoting Binary Format (NRBF), vilket ger effektiv lagring och underhåller typsäkerhet.

Dessa typer använder NRBF, samma effektiva binära format som används av det äldre BinaryFormatter. NRBF-serialisering ger följande viktiga fördelar:

  • Kompakt binär representation: Möjliggör effektiv lagring och överföring.
  • Inbyggd typinformation: Bevarar exakta .NET-typer under tur och retur-åtgärder.
  • Kompatibilitet mellan processer: Fungerar mellan olika .NET-program.
  • Automatisk serialisering: Typer serialiserar utan anpassad kod.

Anmärkning

Metoder som SetData() utför en kopieringsåtgärd som serialiserar data omedelbart, vilket säkerställer att urklippsdata bevaras även efter att den aktuella processen har avslutats. Om du använder DataObject typen direkt med SetDataObject(dataObject, copy)kan du styra när serialiseringen sker. Om du ställer in parametern copytrue (standard) framtvingas omedelbar serialisering, medan false defers serialisering tills det behövs. Med copy inställt på false och data hämtas i samma process är serialisering kanske inte nödvändigt, men data sparas inte när processen har avslutats.

Teknisk information finns i .NET Remoting Binary Format-specifikationen.

Klasser som stöder NRBF-kodade data implementeras i System.Formats.Nrbf namnområdet.

Typsäkerhetsgarantier

Windows Forms innehåller flera säkerhetsmekanismer för dessa inbyggda typer:

  • Exakt typmatchning. TryGetData returnerar endast den begärda typen.
  • Automatisk validering. Windows Forms verifierar typkompatibilitet under deserialisering.
  • Ingen godtycklig kodkörning. Till skillnad från anpassade typer med BinaryFormatter kan dessa typer inte köra skadlig kod.
  • Innehållsverifiering krävs. Du måste fortfarande verifiera datainnehåll och intervall för din programlogik.
  • Inga storleksbegränsningar. Stora matriser eller bitmappar begränsas inte automatiskt. Övervaka minnesanvändning.

Primitiva typer som stöds

Följande primitiva typer fungerar smidigt med urklipps- och DataObject-åtgärder. Du behöver inte anpassad serialisering eller konfiguration. Urklippssystemet hanterar automatiskt dessa inbyggda .NET-typer:

  • bool, byte, char, decimal, double, short, intoch long.
  • sbyte, ushort, uint, ulong, floatoch string.
  • TimeSpan och DateTime.

Följande exempel visar hur dessa primitiva typer fungerar direkt med SetData() och TryGetData<T>() metoder:

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

Samlingar av primitiva typer

Matriser och allmänna listor över primitiva typer som stöds fungerar utan extra konfiguration. Tänk dock på följande begränsningar:

  • Alla matris- och listelement måste ha stöd för primitiva typer.
  • Undvik string[] och List<string> eftersom NRBF-formatet har komplexiteten att hantera null-värden i strängsamlingar.
  • Lagra strängar individuellt eller använd JSON-serialisering för strängsamlingar.

I följande exempel visas hur matriser och listor kan sättas på urklippet:

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-typer

Vanliga grafiktyper från System.Drawing namnområdet fungerar sömlöst med urklipp och DataObject åtgärder. Dessa typer är användbara för program som fungerar med visuella element och som behöver överföra ritningsrelaterade data mellan komponenter eller program. Tänk på att serialisering av en Bitmap kan förbruka en stor mängd minne, särskilt för stora bilder. Följande typer stöds:

  • Point, PointF, Rectangle, . RectangleF
  • Size, SizeF, Color.
  • Bitmap (kan förbruka betydande minne när det serialiseras).

Följande exempel visar hur dessa grafiktyper kan användas med Urklippsåtgärder:

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

Arbeta med anpassade typer

När du använder SetDataAsJson<T>(String, T) och TryGetData med anpassade typer hanterar System.Text.Json serialiseringen automatiskt. Många typer fungerar utan någon särskild konfiguration – rekord, enkla klasser och strukturer med offentliga egenskaper serialiseras sömlöst.

Enkla typer som fungerar utan attribut

De enklaste anpassade typerna kräver inte någon särskild 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

Använda JSON-attribut för avancerad kontroll

Använd System.Text.Json endast attribut när du behöver anpassa serialiseringsbeteendet. Omfattande vägledning om System.Text.Json serialisering, attribut och avancerade konfigurationsalternativ finns i JSON-serialisering och deserialisering i .NET.

I följande exempel visas hur du kan använda JSON-attribut för att styra serialisering:

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

Exempel: Urklippsåtgärder med anpassade typer

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

Försiktighet

användning av BinaryFormatter stöd rekommenderas inte. Använd den bara som en tillfällig migreringsbrygga för äldre program som inte omedelbart kan migrera till de nya typsäkra API:erna.

Om du måste fortsätta att använda BinaryFormatter för Urklippsåtgärder i .NET 10 aktiverar du begränsat stöd via explicit konfiguration. Den här metoden medför betydande säkerhetsrisker och kräver flera steg.

För de fullständiga stegvisa instruktionerna, se Aktivera klippbordsstöd för BinaryFormatter (rekommenderas inte). Allmän migreringsvägledning finns i migreringsguiden för BinaryFormatter.

Säkerhetsvarningar och risker

BinaryFormatter är i sig osäker och inaktuell av följande skäl:

  • Sårbarheter för godtycklig kodkörning: Angripare kan köra skadlig kod under deserialiseringen och utsätta programmet för fjärrattacker.
  • Överbelastningsattacker: Skadliga urklippsdata kan förbruka överdrivet mycket minne eller CPU-resurser, vilket kan orsaka krascher eller instabilitet.
  • Risker för informationsläckage: Angripare kan extrahera känsliga uppgifter från minnet.
  • Inga säkerhetsgränser: Formatet är i grunden osäkert och konfigurationsinställningarna kan inte skydda det.

Aktivera endast det här stödet som en tillfällig brygga när du uppdaterar programmet för att använda de nya typsäkra API:erna.

Detaljerade säkerhetsriktlinjer och konfigurationssteg finns i Säkerhetsvarningar och risker i instruktioner.

Implementera säkerhetsfokuserade typlösare

Även med BinaryFormatter aktiverat måste du implementera typlösare för att begränsa deserialisering till explicit godkända typer. Följ dessa riktlinjer:

  • Använd explicita tillåtna listor. Avvisa alla typer som inte uttryckligen godkänts.
  • Verifiera typnamn. Kontrollera att typnamn exakt matchar förväntade värden.
  • Begränsa till viktiga typer. Inkludera endast de typer som krävs för urklippsfunktionen.
  • Generera undantag för okända typer. Avvisa tydligt obehöriga typer.
  • Granska regelbundet. Granska och uppdatera den tillåtna listan efter behov.

Fullständiga implementeringsexempel och kodexempel finns i Implementera säkerhetsfokuserade typlösare i instruktionsguiden.

Använd AI för att migrera urklippskod

Migrering av Urklippsåtgärder från .NET 8 till .NET 10 innebär systematiska kodändringar i flera filer och klasser. AI-verktyg som GitHub Copilot kan hjälpa dig att påskynda migreringen genom att identifiera äldre mönster, föreslå moderna ersättningar och skapa testscenarier. I stället för att manuellt söka igenom din kodbas och konvertera varje Urklippsåtgärd individuellt kan du använda AI för att hantera repetitiva uppgifter medan du fokuserar på att validera resultat och hantera kantfall.

Följande avsnitt visar specifika promptstrategier för olika aspekter av Urklippsmigrering, från att hitta problematiska kodmönster till att skapa robusta JSON-serialiserbara typer och omfattande testpaket.

Använd AI för att identifiera äldre urklippsmönster

Använd Copilot för att genomsöka din kodbas och hitta urklippsåtgärder som behöver migreras. Detta hjälper dig att förstå omfattningen av de ändringar som krävs innan du påbörjar det faktiska migreringsarbetet.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använda AI för att konvertera GetData() till TryGetData<T>()

Använd Copilot för att konvertera föråldrade GetData() anrop till det nya typsäkra TryGetData<T>() mönstret. Den här konverteringen innehåller korrekt felhantering och eliminerar osäker gjutning.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använda AI för att migrera SetData() till SetDataAsJson<T>()

Använd Copilot för att konvertera lagring av anpassade objekt från den föråldrade SetData() metoden till den nya SetDataAsJson<T>() metoden. Detta säkerställer att dina anpassade objekt serialiseras korrekt till urklipp.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använda AI för att skapa JSON-serialiserbara datamodeller

Använd Copilot för att utforma anpassade typer som fungerar sömlöst med SetDataAsJson<T>() och TryGetData<T>(). Detta inkluderar att lägga till lämpliga attribut för egenskaper som behöver särskild hantering.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använd AI för att generera typsäkra omslutningsmetoder

Använd Copilot för att skapa omslutningsmetoder som kapslar in de nya Urklipps-API:erna och ger rena gränssnitt för programmets specifika datatyper.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använda AI för att skapa omfattande tester

Använd Copilot för att generera testpaket som verifierar att urklippsmigreringen fungerar korrekt, inklusive serialiseringstester och scenarier för felhantering.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.

Använda AI för att verifiera migreringsresultat

Använd Copilot för att granska din migrerade kod och identifiera potentiella problem eller områden där migreringen kanske inte är klar.

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 drivs av AI, så överraskningar och misstag är möjliga. Mer information finns i vanliga frågor och svar om användning av Copilot.