この記事では、Windows フォームのクリップボードとドラッグ アンド ドロップ操作を.NET 10 の新しいタイプ セーフ API にアップグレードする方法について説明します。 新しい Clipboard.TryGetData メソッドと Clipboard.SetDataAsJson<T>(String, T) メソッドを使用する方法、変更なしで動作する組み込み型を理解する方法、および BinaryFormatterの削除後にカスタム型とレガシ データを処理するための戦略を見つけ出す方法について説明します。
BinaryFormatter セキュリティの脆弱性により、.NET 9 のランタイムから削除されました。 この変更により、カスタム オブジェクトを使用したクリップボードとドラッグ アンド ドロップ操作が中断されました。 .NET 10 では、JSON シリアル化とタイプ セーフメソッドを使用してこの機能を復元し、セキュリティを強化し、エラー処理とクロスプロセス互換性を向上させる新しい API が導入されています。
Clipboard.SetData(String, Object) シリアル化に BinaryFormatter を必要とするカスタム型では機能しなくなりました。 このメソッドは、データを直ちにシリアル化するコピー操作 (既定) を実行しますが、削除されたため、 BinaryFormatter が必要な型ではシリアル化が失敗するようになりました。
Clipboard.GetData(String) は .NET 10 では使用されなくなりました。 逆シリアル化に BinaryFormatter が必要だが、有効になっていない場合、 GetData() は NotSupportedException インスタンスを返します。 新しい Clipboard.TryGetData メソッドと Clipboard.SetDataAsJson<T>(String, T) メソッドを使用して、カスタム オブジェクトのタイプ セーフな操作と JSON シリアル化を行います。
次のセクションでは、詳細な移行ガイダンスを提供し、変更なしで動作する型について説明し、新しい開発とレガシ データの両方のシナリオを処理する方法を示します。
[前提条件]
続行する前に、次の概念を確認してください。
- .NET 9 より前のクリップボードとドラッグアンドドロップのシナリオで、アプリケーションがどのように
BinaryFormatterを使用していたか。 -
BinaryFormatterの削除につながったセキュリティの脆弱性。 -
System.Text.Jsonシリアル化パターンとその制限事項を操作する方法。
詳細については、次の記事を参照してください。
BinaryFormatter の削除による破壊的変更
.NET 9 で BinaryFormatter を削除すると、Windows フォームがクリップボードやドラッグ アンド ドロップ操作をカスタム型で処理する方法が根本的に変わります。 これらの変更は既存のコード パターンに影響を与え、機能を維持するには慎重な移行が必要です。
カスタム型が自動的にシリアル化されなくなりました
.NET 8 以前では、 SetData()を呼び出すことによって、シリアル化可能なカスタム オブジェクトをクリップボードに配置できます。
BinaryFormatterはシリアル化を自動的に処理します。 .NET 9 以降、 SetData() はデータを直ちにシリアル化するコピー操作を実行しますが、このシリアル化は削除されたため、 BinaryFormatter が必要な型では失敗します。
次のコードは機能しなくなりました。
[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
表示される内容
-
SetData()メソッドは、例外をスローせずに完了します。 - データはクリップボードに配置されますが、
BinaryFormatterを必要とする型のシリアル化は失敗します。 - 後で
GetData()によってデータの取得を試みると、BinaryFormatterが必要だが有効になっていないことを示すNotSupportedExceptionインスタンスが返されます。
移行ガイダンス
新しい SetDataAsJson<T>() メソッドを使用するか、 string または byte[]に手動でシリアル化します。 詳細については、「 カスタム型の操作」 セクションを参照してください。
GetData() は廃止されています。代わりに TryGetData<T>() を使用してください
従来の GetData() メソッドは、.NET 10 では使用されなくなりました。 このメソッドはほとんどの場合、データを正常に返しますが、逆シリアル化にBinaryFormatterが必要であり、有効になっていない場合、GetData()はNotSupportedExceptionが必要であることを示すBinaryFormatter インスタンスを返します。 エラー処理とタイプ セーフを向上させるために、新しいタイプ セーフな TryGetData<T>() メソッドに移行する必要があります。
次の例は、避けるべき古いパターンを示しています。
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
代わりに、 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
TryGetData<T>() の利点
- 型安全: 型変換する必要はありません。このメソッドは要求された正確な型を返します。
- エラー処理のクリア: null または例外パターンを使用する代わりに、ブール値の成功インジケーターを返します。
- 将来の対応: 新しいシリアル化メソッドとレガシ データのサポートを使用するように設計されています。
影響を受けるコードを識別する方法
検索対象:
- メソッド全体がデータ型に関係なく廃止されているため、
GetData()の呼び出しはすべて不要です。 -
DataObject.GetData()とIDataObject.GetData()はドラッグアンドドロップ操作で使用されます。
移行ガイダンス
すべての GetData() 使用法をタイプ セーフな TryGetData<T>() メソッドに置き換えます。 すべてのオーバーロードの包括的な例については、「 新しいタイプ セーフ API」 セクションを参照してください。
新しい型安全 API
.NET 10 では、クリップボードとドラッグ アンド ドロップ操作に対して、型の安全性、より優れたエラー処理、JSON シリアル化のサポートを提供する 3 つの新しい API ファミリが導入されています。
- TryGetData データを取得するためのメソッド
- SetDataAsJson<T>(String, T) データを格納するためのメソッド
- ITypedDataObject ドラッグ アンド ドロップ操作用のインターフェイス
TryGetData<T>() メソッド
TryGetData<T>() ファミリは、古いGetData()メソッドに代わるものになっています。 これは、タイプ セーフな取得と、クリップボード操作の成功または失敗を明確に示します。
基本的なタイプ セーフな取得
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
カスタム JSON 型
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>() メソッド
これらのメソッドは、タイプ セーフなストレージを使用した System.Text.Json を使用した JSON の自動シリアル化を提供します。
カスタム形式を指定する
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
自動形式推論
データ形式として型名を指定すると、 TryGetData<T> は形式を自動的に推論できます。
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 インターフェイス
ITypedDataObject インターフェイスを使用すると、型指定されたメソッドでIDataObjectを拡張することで、タイプ セーフなドラッグ アンド ドロップ操作が可能になります。
.NET 10 以降では、 DataObject (ドラッグ アンド ドロップ のシナリオで一般的な種類) によって ITypedDataObjectが実装されます。
ドラッグ アンド ドロップシナリオで ITypedDataObject を使用する
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
JSON シリアル化を必要としない型
組み込みの .NET 型の多くは、JSON シリアル化や BinaryFormatter サポートを必要とせずにクリップボード操作で動作します。 これらの型は、効率的なストレージを提供し、型の安全性を維持する .NET リモート処理バイナリ形式 (NRBF) に自動的にシリアル化されます。
これらの型では、従来の BinaryFormatterで使用されるのと同じ効率的なバイナリ形式である NRBF が使用されます。 NRBF シリアル化には、次の主な利点があります。
- コンパクトなバイナリ表現:効率的なストレージと転送を可能にします。
- 組み込みの型情報: ラウンド トリップ操作中に正確な .NET 型を保持します。
- プロセス間の互換性: 異なる .NET アプリケーション間で動作します。
- 自動シリアル化: 型は、カスタム コードなしでシリアル化されます。
注
SetData()などのメソッドは、データを直ちにシリアル化するコピー操作を実行し、現在のプロセスが終了した後でもクリップボードのデータが保持されるようにします。
DataObjectでSetDataObject(dataObject, copy)型を直接使用する場合は、シリアル化が発生するタイミングを制御できます。
copy パラメーターを true (既定値) に設定すると、強制的に即時シリアル化されますが、falseは必要になるまでシリアル化を延期します。
copyを false に設定し、同じプロセスでデータを取得する場合、シリアル化は必要ない場合がありますが、データはプロセスの終了後も保持されません。
技術的な詳細については、 .NET リモート処理バイナリ形式の仕様を参照してください。
NRBF でエンコードされたデータをサポートするクラスは、 System.Formats.Nrbf 名前空間に実装されます。
型安全性保証
Windows フォームには、次の組み込み型のいくつかの安全メカニズムが用意されています。
- 正確な型の一致。 TryGetData は、要求された型のみを返します。
- 自動検証。 Windows フォームは、逆シリアル化中に型の互換性を検証します。
- 任意のコード実行はありません。 BinaryFormatter を使用したカスタム型とは異なり、これらの型は悪意のあるコードを実行できません。
- コンテンツの検証が必要です。 アプリケーション ロジックのデータコンテンツと範囲を検証する必要があります。
- サイズの制約はありません。 大きな配列やビットマップは自動的に制限されません。 メモリ使用量を監視します。
サポートされているプリミティブ型
次のプリミティブ型は、クリップボードと DataObject 操作でシームレスに動作します。 カスタムのシリアル化や構成は必要ありません。 クリップボード システムは、次の組み込みの .NET 型を自動的に処理します。
-
bool、byte、char、decimal、double、short、int、long。 -
sbyte、ushort、uint、ulong、float、およびstringがあります。 -
TimeSpanとDateTime.
次の例は、これらのプリミティブ型が SetData() メソッドおよび TryGetData<T>() メソッドで直接動作する方法を示しています。
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
プリミティブ型のコレクション
サポートされているプリミティブ型の配列とジェネリック リストは、追加の構成なしで機能します。 ただし、次の制限事項に注意してください。
- すべての配列要素とリスト要素は、サポートされているプリミティブ型である必要があります。
- NRBF 形式には文字列コレクション内の null 値の処理が複雑であるため、
string[]とList<string>は避けてください。 - 文字列を個別に格納するか、文字列コレクションに JSON シリアル化を使用します。
次の例は、クリップボードで配列とリストを設定する方法を示しています。
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 の種類
System.Drawing名前空間の一般的なグラフィックスの種類は、クリップボードとDataObject操作とシームレスに連携します。 これらの型は、ビジュアル要素を操作し、コンポーネントまたはアプリケーション間で描画関連のデータを転送する必要があるアプリケーションに役立ちます。
Bitmapをシリアル化すると、特に大きなイメージの場合、大量のメモリが消費される可能性があることに注意してください。 次の種類がサポートされています。
-
Point、PointF、Rectangle、RectangleF。 -
Size、SizeF、Color。 -
Bitmap(シリアル化時に大量のメモリを消費する可能性があります)。
次の例は、これらのグラフィックスの種類をクリップボード操作で使用する方法を示しています。
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
カスタム型の操作
カスタム型で SetDataAsJson<T>(String, T) と TryGetData を使用すると、 System.Text.Json はシリアル化を自動的に処理します。 多くの型は、特別な構成なしで動作します。レコード、単純なクラス、パブリック プロパティを持つ構造体はシームレスにシリアル化されます。
属性なしで機能する単純型
ほとんどの単純なカスタム型では、特別な構成は必要ありません。
// 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
高度な制御に JSON 属性を使用する
System.Text.Json属性は、シリアル化の動作をカスタマイズする必要がある場合にのみ使用します。
System.Text.Jsonシリアル化、属性、および高度な構成オプションに関する包括的なガイダンスについては、「.NET での JSON シリアル化と逆シリアル化」を参照してください。
次の例は、JSON 属性を使用してシリアル化を制御する方法を示しています。
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
例: カスタム型を使用したクリップボード操作
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
BinaryFormatter のサポートを有効にする (推奨されません)
注意事項
BinaryFormatter サポートは 推奨されません。 これは、新しいタイプ セーフな API にすぐに移行できないレガシ アプリケーションの一時的な移行ブリッジとしてのみ使用します。
.NET 10 でクリップボード操作に BinaryFormatter を引き続き使用する必要がある場合は、明示的な構成によって制限付きサポートを有効にします。 このアプローチでは、重大なセキュリティ リスクが伴い、いくつかの手順が必要です。
詳細な手順については、「 BinaryFormatter クリップボードのサポートを有効にする (推奨されません)」を参照してください。 一般的な移行ガイダンスについては、 BinaryFormatter 移行ガイドを参照してください。
セキュリティの警告とリスク
BinaryFormatter は本質的に安全でなくなり、次の理由で非推奨になります。
- 任意のコード実行の脆弱性: 攻撃者は逆シリアル化中に悪意のあるコードを実行し、アプリケーションをリモート攻撃にさらす可能性があります。
- サービス拒否攻撃: 悪意のあるクリップボード データは、過剰なメモリや CPU リソースを消費し、クラッシュや不安定を引き起こす可能性があります。
- 情報漏えいのリスク: 攻撃者はメモリから機密データを抽出する可能性があります。
- セキュリティ境界なし: この形式は基本的に安全ではなく、構成設定ではセキュリティで保護できません。
このサポートを一時的なブリッジとして有効にするのは、新しいタイプ セーフ API を使用するようにアプリケーションを更新する場合のみです。
詳細なセキュリティ ガイドラインと構成手順については、ハウツー ガイドの 「セキュリティの警告とリスク 」を参照してください。
セキュリティに重点を置いた型リゾルバーを実装する
BinaryFormatterを有効にした場合でも、型リゾルバーを実装して、逆シリアル化を明示的に承認された型に制限する必要があります。 次のガイドラインに従います。
- 明示的な許可リストを使用します。 明示的に承認されていない型を拒否します。
- 型名を検証します。 型名が予想される値と正確に一致していることを確認します。
- 必須の型に制限します。 クリップボード機能に必要な型のみを含めます。
- 不明な型の例外をスローします。 承認されていない型を明確に拒否します。
- 定期的に確認します。 必要に応じて、許可リストを監査して更新します。
完全な実装例とコード サンプルについては、ハウツー ガイド の「セキュリティに重点を置いた型リゾルバーの実装 」を参照してください。
AI を使用してクリップボード コードを移行する
クリップボード操作を .NET 8 から .NET 10 に移行するには、複数のファイルとクラス間で体系的なコード変更が必要です。 GitHub Copilot などの AI ツールは、従来のパターンを識別し、最新の代替候補を提案し、テスト シナリオを作成することで、移行を高速化するのに役立ちます。 コードベースを手動で検索して各クリップボード操作を個別に変換する代わりに、AI を使用して反復的なタスクを処理しながら、結果の検証とエッジ ケースの処理に重点を置くことができます。
次のセクションでは、問題のあるコード パターンの検出から、堅牢な JSON シリアル化可能な型と包括的なテスト スイートの作成まで、クリップボードの移行のさまざまな側面に対する具体的なプロンプト戦略を示します。
AI を使用して従来のクリップボード パターンを識別する
Copilot を使用してコードベースをスキャンし、移行が必要なクリップボード操作を見つけます。 これは、実際の移行作業を開始する前に必要な変更の範囲を理解するのに役立ちます。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して GetData() を TryGetData<T>() に変換する
Copilot を使用して、古い GetData() 呼び出しを新しいタイプ セーフな TryGetData<T>() パターンに変換します。 この変換には、適切なエラー処理が含まれており、安全でないキャストを排除します。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して SetData() を SetDataAsJson<T>() に移行する
Copilot を使用して、カスタム オブジェクト ストレージを古い SetData() メソッドから新しい SetDataAsJson<T>() アプローチに変換します。 これにより、カスタム オブジェクトがクリップボードに正しくシリアル化されます。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して JSON シリアル化可能なデータ モデルを作成する
Copilot を使用して、 SetDataAsJson<T>() と TryGetData<T>()でシームレスに動作するカスタム型を設計します。 これには、特別な処理を必要とするプロパティに適切な属性を追加する必要があります。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して型安全なラッパー メソッドを生成する
Copilot を使用して、新しいクリップボード API をカプセル化し、アプリケーションの特定のデータ型にクリーンなインターフェイスを提供するラッパー メソッドを作成します。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して包括的なテストを作成する
Copilot を使用して、ラウンドトリップシリアル化テストやエラー処理シナリオなど、クリップボードの移行が正しく動作することを確認するテスト スイートを生成します。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
AI を使用して移行結果を検証する
Copilot を使用して、移行されたコードを確認し、移行が完了していない可能性がある潜在的な問題や領域を特定します。
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 では AI を利用しているため、想定外のことや間違いが起こる可能性があります。 詳細については、「Copilot の一般的な使用に関する FAQ」を参照してください。
関連コンテンツ
.NET Desktop feedback