Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este artigo mostra como atualizar sua área de transferência do Windows Forms e operações de arrastar e soltar para as novas APIs seguras para tipos no .NET 10. Você aprenderá como usar os novos Clipboard.TryGetData e Clipboard.SetDataAsJson<T>(String, T) métodos, entenderá quais tipos integrados funcionam sem alterações, e descobrirá estratégias para lidar com tipos personalizados e dados herdados após a remoção do BinaryFormatter.
BinaryFormatter foi removido do tempo de execução no .NET 9 devido a vulnerabilidades de segurança. Essa alteração quebrou as operações da área de transferência e de arrastar e soltar com objetos personalizados. O .NET 10 apresenta novas APIs que usam serialização JSON e métodos seguros para tipos para restaurar essa funcionalidade, melhorar a segurança e fornecer melhor tratamento de erros e compatibilidade entre processos.
Clipboard.SetData(String, Object) já não funciona com tipos personalizados que requerem BinaryFormatter para a serialização. Esse método executa uma operação de cópia (por padrão) que serializa dados imediatamente, mas essa serialização agora falha para tipos que precisam BinaryFormatter porque foram removidos.
Clipboard.GetData(String) está obsoleta no .NET 10. Quando BinaryFormatter é necessário para a desserialização, mas não está habilitado, GetData() retorna uma NotSupportedException instância. Use os novos métodos Clipboard.TryGetData e Clipboard.SetDataAsJson<T>(String, T) para operações do tipo seguras e a serialização JSON de objetos personalizados.
As seções a seguir fornecem diretrizes detalhadas de migração, explicam quais tipos funcionam sem alterações e mostram como lidar com cenários de dados herdados e de desenvolvimento novos.
Pré-requisitos
Antes de continuar, analise estes conceitos:
- Como os aplicativos eram usados
BinaryFormatterem cenários de área de transferência e de arrastar e soltar antes do .NET 9. - As vulnerabilidades de segurança que levaram à remoção do
BinaryFormatter. - Como trabalhar com
System.Text.Jsonpadrões de serialização e suas limitações.
Para obter mais informações, consulte estes artigos:
- Riscos de desserialização no uso de BinaryFormatter e tipos relacionados.
- Guia de migração BinaryFormatter.
Alterações disruptivas devido à remoção do BinaryFormatter
A remoção de BinaryFormatter no .NET 9 altera fundamentalmente a maneira como o Windows Forms lida com operações de área de transferência e arrastar e soltar com tipos personalizados. Essas alterações afetam os padrões de código existentes e exigem uma migração cuidadosa para manter a funcionalidade.
Os tipos personalizados não são mais serializados automaticamente
No .NET 8 e versões anteriores, você pode colocar qualquer objeto personalizado serializável na área de transferência chamando SetData(). O BinaryFormatter lidava com a serialização automaticamente. A partir do .NET 9, SetData() ainda executa uma operação de cópia que serializa dados imediatamente, mas essa serialização falha para tipos que exigem BinaryFormatter porque foram removidos.
O código a seguir não funciona mais:
[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
O que poderá ver
- O
SetData()método é concluído sem lançar uma exceção. - Os dados são colocados na área de transferência, mas a serialização falha para tipos que exigem
BinaryFormatter. - Tentativas posteriores de recuperar os dados com
GetData()retornam uma instância de NotSupportedException que indica queBinaryFormatteré necessário, mas não está habilitado.
Orientações em matéria de migração
Use o novo SetDataAsJson<T>() método ou serialize manualmente para um string ou byte[]. Para obter detalhes, consulte a seção Trabalhar com tipos personalizados .
GetData() está obsoleto - use TryGetData<T>() em vez disso
O método herdado GetData() está obsoleto no .NET 10. Esse método retorna dados com êxito na maioria dos casos, mas quando BinaryFormatter é necessário para a desserialização e não está habilitado, GetData() retorna uma instância NotSupportedException indicando que BinaryFormatter é necessária. Você deve migrar para os novos métodos seguros de tipo TryGetData<T>() para um melhor tratamento de erros e segurança de tipo.
O exemplo a seguir mostra o padrão obsoleto que você deve evitar:
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
Em vez disso, use a abordagem moderna de tipo seguro com 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
Benefícios do TryGetData<T>()
- Segurança do tipo: Não há necessidade de fundição — o método retorna o tipo exato solicitado.
- Tratamento claro de erros: retorna um indicador de sucesso booleano em vez de usar padrões nulos ou de exceção.
- Preparado para o futuro: Projetado para trabalhar com novos métodos de serialização e suporte a dados herdados.
Como identificar o código afetado
Procure:
- Qualquer
GetData()chamada, já que todo o método é obsoleto, independentemente do tipo de dados. -
DataObject.GetData()eIDataObject.GetData()usados em operações de arrastar e soltar.
Orientações em matéria de migração
Substitua todos os usos de GetData() por métodos TryGetData<T>() seguros de tipo. Para obter exemplos abrangentes de todas as sobrecargas, consulte a seção Novas APIs seguras para tipos .
Novas APIs seguras para tipos
O .NET 10 introduz três novas famílias de API que garantem segurança de tipos, aprimoram o tratamento de erros e oferecem suporte à serialização JSON para operações de transferência e arrastar e soltar.
- TryGetData Métodos de recuperação de dados
- SetDataAsJson<T>(String, T) Métodos de armazenamento de dados
- ITypedDataObject Interface para operações de arrastar e soltar
Métodos TryGetData<T>()
A TryGetData<T>() família substitui o método obsoleto GetData() . Ele fornece recuperação de tipo segura e uma indicação clara de sucesso ou falha para operações na sua área de transferência.
Recuperação básica segura para tipos
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
Tipos JSON personalizados
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
Métodos SetDataAsJson<T>()
Esses métodos fornecem serialização JSON automática usando System.Text.Json com armazenamento seguro de tipo.
Especificar um formato personalizado
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
Inferência automática de formato
Ao especificar o nome do tipo como o formato de dados, TryGetData<T> pode inferir o formato automaticamente:
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
Interface ITypedDataObject
A ITypedDataObject interface permite operações de arrastar e soltar com segurança de tipos, ao estender IDataObject com métodos tipados.
A partir do .NET 10, DataObject (um tipo comum em cenários de arrastar e soltar) implementa ITypedDataObject.
Usar ITypedDataObject em cenários de arrastar e soltar
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
Tipos que não exigem serialização JSON
Muitos tipos internos de .NET funcionam com operações da área de transferência sem exigir serialização JSON ou suporte a blocos de código BinaryFormatter. Esses tipos serializam automaticamente no .NET Remoting Binary Format (NRBF), que fornece armazenamento eficiente e mantém a segurança do tipo.
Esses tipos usam NRBF, o mesmo formato binário eficiente usado pelo legado BinaryFormatter. A serialização NRBF fornece estes principais benefícios:
- Representação binária compacta: Permite armazenamento e transferência eficientes.
- Informações de tipo incorporadas: Preserva os tipos exatos do .NET durante operações de ida e volta.
- Compatibilidade entre processos: funciona entre diferentes aplicativos .NET.
- Serialização automática: tipos serializados sem código personalizado.
Observação
Métodos como SetData() executam uma operação de cópia que serializa os dados imediatamente, garantindo que os dados da área de transferência persistam mesmo após o término do processo atual. Se utilizares o tipo diretamente com DataObject, poderás controlar quando ocorre a serialização com SetDataObject(dataObject, copy). Definir o parâmetro como copy (o padrão) força a serialização imediata, enquanto true adia a false serialização até que seja necessário. Com copy definido como false e os dados são recuperados no mesmo processo, a serialização pode não ser necessária, mas os dados não persistirão após a saída do processo.
Para mais detalhes técnicos, consulte a especificação do .NET Remoting Binary Format.
As classes que suportam dados codificados em NRBF são implementadas no System.Formats.Nrbf namespace.
Garantias de segurança de tipo
O Windows Forms fornece vários mecanismos de segurança para esses tipos incorporados.
- Correspondência exata de tipos. TryGetData retorna apenas o tipo solicitado.
- Validação automática. O Windows Forms valida a compatibilidade de tipos durante a desserialização.
- Sem execução arbitrária de código. Ao contrário dos tipos personalizados com BinaryFormatter, esses tipos não podem executar código mal-intencionado.
- Validação de conteúdo necessária. Você ainda deve validar o conteúdo e os intervalos de dados para a lógica do aplicativo.
- Sem restrições de tamanho. Grandes matrizes ou bitmaps não são limitados automaticamente. Monitore o uso da memória.
Tipos primitivos suportados
Os seguintes tipos primitivos funcionam perfeitamente com a área de transferência e DataObject as operações. Você não precisa de serialização ou configuração personalizada. O sistema da área de transferência lida automaticamente com os seguintes tipos embutidos do .NET:
-
bool,byte,char,decimal,double,short,int, elong. -
sbyte,ushort, ,uint,ulongfloat, estring. -
TimeSpaneDateTime.
Os exemplos a seguir mostram como esses tipos primitivos funcionam diretamente com SetData() e TryGetData<T>() métodos:
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
Coleções de tipos primitivos
Matrizes e listas genéricas de tipos primitivos suportados funcionam sem configuração extra. No entanto, tenha estas limitações em mente:
- Todos os elementos de matriz e lista devem ser de tipos primitivos suportados.
- Evite
string[]eList<string>porque o formato NRBF tem complexidade ao lidar com valores nulos em coleções de cadeias de caracteres. - Armazene cadeias de caracteres individualmente ou use a serialização JSON para coleções de cadeias de caracteres.
Os exemplos a seguir mostram como matrizes e listas podem ser definidas na área de transferência:
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
Tipos de System.Drawing
Os tipos de gráficos comuns do espaço de nomes System.Drawing funcionam perfeitamente com a área de transferência e as operações DataObject. Esses tipos são úteis para aplicativos que trabalham com elementos visuais e precisam transferir dados relacionados ao desenho entre componentes ou aplicativos. Esteja ciente de que a serialização de um Bitmap pode consumir uma grande quantidade de memória, especialmente para imagens grandes. Os seguintes tipos são suportados:
-
Point,PointF,Rectangle,RectangleF. -
Size,SizeF,Color. -
Bitmap(pode consumir memória significativa quando serializado).
Os exemplos a seguir mostram como estes tipos de gráficos podem ser usados com operações de transferência.
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
Trabalhar com tipos personalizados
Quando você usa SetDataAsJson<T>(String, T) e TryGetData com tipos personalizados, System.Text.Json lida com a serialização automaticamente. Muitos tipos funcionam sem qualquer configuração especial — registros, classes simples e estruturas com propriedades públicas serializam perfeitamente.
Tipos simples que funcionam sem atributos
A maioria dos tipos personalizados simples não requer configuração especial:
// 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
Usar atributos JSON para controle avançado
Use System.Text.Json atributos somente quando precisar personalizar o comportamento de serialização. Para obter orientações abrangentes sobre System.Text.Json serialização, atributos e opções de configuração avançadas, consulte Serialização e desserialização JSON no .NET.
O exemplo a seguir mostra como você pode usar atributos JSON para controlar a serialização:
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
Exemplo: operações da área de transferência com tipos personalizados
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
Ativar suporte BinaryFormatter (não recomendado)
Atenção
BinaryFormatter O suporte não é recomendado. Use-o apenas como uma ponte de migração temporária para aplicações legadas que não podem migrar imediatamente para as novas APIs seguras em termos de tipos.
Se precisar continuar a usar BinaryFormatter para operações de clipboard no .NET 10, habilite o suporte limitado por meio de configuração explícita. Esta abordagem acarreta riscos de segurança significativos e requer várias etapas.
Para obter instruções passo a passo completas, veja Ativar suporte para a área de transferência do BinaryFormatter (não recomendado). Para obter orientações gerais sobre migração, consulte o Guia de migração BinaryFormatter.
Avisos e riscos de segurança
BinaryFormatter é inerentemente insegura e preterida pelos seguintes motivos:
- Vulnerabilidades de execução arbitrária de código: os invasores podem executar código mal-intencionado durante a desserialização, expondo seu aplicativo a ataques remotos.
- Ataques de negação de serviço: dados mal-intencionados da área de transferência podem consumir memória excessiva ou recursos da CPU, causando falhas ou instabilidade.
- Riscos de divulgação de informações: os invasores podem extrair dados confidenciais da memória.
- Sem limites de segurança: o formato é fundamentalmente inseguro e as definições de configuração não podem protegê-lo.
Habilite esse suporte apenas como uma ponte temporária enquanto você atualiza seu aplicativo para usar as novas APIs seguras para tipos.
Para obter diretrizes de segurança detalhadas e etapas de configuração, consulte Avisos e riscos de segurança no guia de instruções.
Implementar resolvedores de tipo focados na segurança
Mesmo com BinaryFormatter habilitado, você deve implementar resolvedores de tipo para restringir a desserialização a tipos explicitamente aprovados. Siga estas diretrizes:
- Use listas de permissões explícitas. Rejeitar qualquer tipo não explicitamente aprovado.
- Valide nomes de tipo. Certifique-se de que os nomes dos tipos correspondem exatamente aos valores esperados.
- Limite aos tipos essenciais. Inclua apenas os tipos necessários para a funcionalidade da área de transferência.
- Lance exceções para tipos desconhecidos. Rejeite claramente tipos não autorizados.
- Reveja regularmente. Audite e atualize a lista de permissões conforme necessário.
Para obter exemplos completos de implementação e exemplos de código, consulte Implementar resolvedores de tipo focados em segurança no guia de instruções.
Use a IA para migrar o código da área de transferência
A migração de operações de transferência de dados do .NET 8 para o .NET 10 envolve alterações sistemáticas de código em vários ficheiros e classes. Ferramentas de IA como o GitHub Copilot podem ajudar a acelerar sua migração, identificando padrões legados, sugerindo substituições modernas e criando cenários de teste. Em vez de pesquisar manualmente na sua base de código e converter cada operação da área de transferência individualmente, pode-se usar a IA para lidar com tarefas repetitivas enquanto se concentra na validação de resultados e no tratamento de casos extremos.
As seções a seguir mostram estratégias de prompt específicas para diferentes aspetos da migração da área de transferência, desde a localização de padrões de código problemáticos até a criação de tipos serializáveis JSON robustos e pacotes de teste abrangentes.
Utilize a IA para identificar padrões legados da área de transferência
Use o Copilot para verificar sua base de código e localizar operações da área de transferência que precisam de migração. Isso ajuda você a entender o escopo das alterações necessárias antes de iniciar o trabalho de migração real.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Use a IA para converter GetData() em TryGetData<T>()
Use o Copilot para converter chamadas obsoletas GetData() para o novo padrão de tipo seguro TryGetData<T>() . Esta conversão inclui o tratamento adequado de erros e elimina a fundição insegura.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Use a IA para migrar SetData() para SetDataAsJson<T>()
Use o Copilot para converter o armazenamento de objetos personalizados do método obsoleto SetData() para a nova SetDataAsJson<T>() abordagem. Isso garante que seus objetos personalizados sejam serializados corretamente para a área de transferência.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Use a IA para criar modelos de dados serializáveis por JSON
Use o Copilot para projetar tipos personalizados que funcionam perfeitamente com SetDataAsJson<T>() e TryGetData<T>(). Isso inclui a adição de atributos apropriados para propriedades que precisam de tratamento especial.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Use IA para gerar métodos de invólucro seguros para tipos
Use o Copilot para criar métodos wrapper que encapsulem as novas APIs da área de transferência (clipboard) e forneçam interfaces limpas para os tipos de dados específicos da sua aplicação.
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().
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Use a IA para criar testes abrangentes
Use o Copilot para gerar conjuntos de testes que verificam se a migração da área de transferência funciona corretamente, incluindo testes de serialização de ida e volta e cenários de tratamento de erros.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Usar IA para validar resultados de migração
Use o Copilot para revisar seu código migrado e identificar possíveis problemas ou áreas em que a migração pode não estar concluída.
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.
O copiloto é alimentado por IA, por isso surpresas e erros são possíveis. Para obter mais informações, consulte Perguntas frequentes sobre o uso geral do Copilot.
Conteúdo relacionado
.NET Desktop feedback