
1. はじめに
こんにちは、アプリケーションエンジニアの松澤です。普段はC#のネイティブアプリケーション開発を行っています。
少し前となりましたが、AWS re:Invent 2025に参加し、様々なアップデートを現地で体感してきました。私は.NET/C#エンジニアということもあり、AWS Transform for .NETについて興味を持ち注目していたのですが、なんと.NETの枠組みを超え、大幅に強化されていました!これは触れざるを得ないと思い、今回は簡単なモダナイズのデモを行いました。
2. AWS Transform の .NET変換機能が強化!
re:Inventでも発表されましたが、AWS Transform for .NETが、.NETの枠組みを超えて、フルスタックWindowsモダナイズエージェントとして強化されました。
データベースレイヤーの変換対応
アプリケーションレイヤーのモダナイズだけでなく、データベースレイヤーのMicrosoft SQL Server データベースから Amazon Aurora Postgre SQLへのモダナイズにも対応するようになりました。
.NET 自体の変換強化
- モダナイズ
- .NET 10/.NET Standardにモダナイズ可能
- ASP.NET Web FormsをASP.NET Core Blazorにモダナイズ可能
- Entity Frameworkのモダナイズ
- AWS Toolkit for Visual Studio 2026 or 2022(Visual Studio拡張機能)
- transformation-plan.mdによるモダナイズのカスタマイズ
- nextsteps.mdによるジョブ完了後のとるべきアクションのドキュメント化
- KiroなどのAIコンパニオンツールで対応可能
2025年11月に正式リリースされた.NET 10にもばっちり対応しているのは嬉しいですね。
特に私が注目しているのは、AWS Toolkit for Visual Studio 2026 or 2022で、transformation-plan.mdを用いた変換プランのカスタマイズです(2026年1月現在はプレビュー版です)。これまでのモダナイズでは、変換対象のソリューション・プロジェクトを選択して、あとはAWS Transform次第なところもありました。この度、変換プランをカスタマイズできるようになったため、ただアップデートするのではなく、非推奨メソッドや、レガシーな記法をモダナイズすることができるのではないかと感じています。
仕様に合わせてモダナイズができるようになったので、Spec駆動モダナイズといっても過言ではないのかもしれません。
今回は、強化されたAWS Transformを利用して、アプリケーションをどのようにモダナイズしてくれるのか、変換のカスタマイズはどこまで適用されるのか、実際に触って調べていこうと思います。
3. モダナイズのカスタマイズ概要
今回は、簡単なデモ用のWindows Formsアプリケーションを.NET Framework 4.8で作成し、AWS Toolkit for Visual Studio 2026経由でモダナイズを行いました。
モダナイズの手順
Visual Studioからの使い方は、以前Qiitaにて記事を書かせていただきました。流れは変わりありませんので、ぜひこちらをご参考ください。
上記のブログで紹介している手順で、「Generating code transformation plan」のステップに移行すると、「Edit plan」か「Start transformation」が選択できるようになりました。「Edit plan」を選択すると、transformation-plan.md を修正できます。


修正後保存し、「Start transformation」を押下すると、変換のジョブが実行されます。
また、transformation-plan.mdは、UTF-8で保存しなければならないため、Visual Studio上で、ファイルの保存時にUTF-8で保存するように設定しましょう。
なお、AWS Toolkitを用いた変換は、アーティファクトがソリューション配下に作成されるartifactWorkspaceに格納されます。ローカルでその結果を反映して、Commitしなければなりません。Webアプリケーションで行う場合は、新しいブランチにモダナイズ結果が反映されるため、それと比べれば若干使いにくいです。
また、今回変換に用いたソリューションはGitHub上に公開しています。変換の様子などはブランチを分けていますので、ぜひご参考ください。
変換してほしい構文
今回のモダナイズでは、.NET Framework 4.8(C# 7.8)から.NET 10(C# 14)に変換を行います。当然C#のメジャーバージョンが7上がるため、利用できる文法も大きく増えます。
今回は変換してほしい構文を5つピックアップして、モダナイズ対象のソリューションで実装しました。
using宣言(C# 8.0~)
usingステートメントはSQLコネクションなどのアンマネージドリソースの破棄を自動化する構文です。{} によって明示的にリソースの利用範囲を記載する必要がありました。
C# 8.0からは変数宣言時にusingをつけることで簡略化できるようになりました。*1宣言時のスコープから外れると、リソースを解放してくれます。
// Old using (var connection = new MySqlConnection(ConnectionString)) { // ロジック } // New using var connection = new MySqlConnection(ConnectionString); // ロジック
interfaceの修飾子(C# 8.0~)
interfaceで定義するフィールド・メソッドは明示的にpublicのインスタンスフィールド・メソッドしか定義できませんでしたが、C# 8.0より、interfaceに修飾子(public・static)を付与できるようになりました。*2
今回の検証では、元々暗黙的にpublicで宣言されていたフィールド・メソッドに明示的にpublicを付与するように検証します。
// Old string AddressInput { get; } void DisplayUsers(object users); // New public string AddressInput { get; } public void DisplayUsers(object users);
コレクション式(C# 12~)
コレクション式*3はC# 12の新機能です。コレクション型の初期化を、型 変数名 = [] というシンプルな形で実装することができます。
// Old var users = new List<UserModel> { new UserModel { Id = 1, Name = "Alice" }, new UserModel { Id = 2, Name = "Bob" }, }; // New List<UserModel> users = [ new UserModel { Id = 1, Name = "Alice" }, new UserModel { Id = 2, Name = "Bob" }, ];
SecurityPermission クラス(非推奨)
SecurityPermission クラス*4はコードに適用されるセキュリティのアクセス許可セットについてのクラスです。現在どの.NETのバージョンでも非推奨となっています。
var permission = new SecurityPermission(SecurityPermissionFlag.Execution);
Thread.Abortメソッド(非推奨)
Thread.Abortメソッド*5は、スレッドが呼び出された対象のスレッドで、そのスレッドの終了プロセスを開始します。.NET 5(C#9) 以降のバージョンではコンパイルエラーが生じます。
var t = new Thread(() => { while (true) { } }); t.Start(); t.Abort();
4. モダナイズの実践
1. デフォルトのEdit planを適用
まずは、ベンチマークとしてtransformation-plan.md をカスタマイズせずにモダナイズを実行します。デフォルトでは、下記のジョブプランが作成されました。

.NET 10への変換には約30分かかり、そのあとのコンパイルエラーの対処に約30分かかったため合計で1時間かかりました。

無事に、.NET 10にはモダナイズされ、すべてのステップが完了しました。起動も無事にできました。

結果
特に変換プランで指定していませんでしたが、下記の変換を行ってくれました。
ファイルスコープの名前空間*6
変化した構文は、C# 10で利用できるようになったファイルスコープの名前空間です。ネストが下がって可読性が上がりました。ただ、すべてのファイルのnamespaceが修正されたわけではなく、修正されていないファイルもありました。
// Old namespace WindowsFormsAppTransformTest.Presenter{ internal class UserPresenter { } } // New namespace WindowsFormsAppTransformTest.Presenter; internal class UserPresenter { }
null許容参照型への変換*7
変換したソースでは、string型(参照型)のフィールドにC# 8.0以上で利用可能なnull許容参照型が適用されました。Null Safetyなコードになりました。
// Old public string UserName { get; set; } // New public string? UserName { get; set; }
非推奨メソッドの変換
SecurityPermissionクラス、Thread.Abortメソッドに関しては、どちらも変換を行ってくれました。ドキュメントコメント/コメントにて、.NET 10では利用できない構文であることを記してくれました。

ただし、using宣言、interfaceの修飾子、コレクション式の変換は行われませんでした。デフォルトの変換プランだと、最低限非推奨となっているメソッドやエラーを修正してくれるようでした。
2. transformation-plan.mdのカスタマイズ
手順は先ほどと同じですが、途中でtransformation-plan.mdを修正します。using宣言、interfaceの修飾子、コレクション式の変換を行うようにカスタマイズしました。カスタマイズ後のtransformation-plan.mdは下記の通りになります。(※ただし、コレクション式は何度試してもうまくStepとして認識してくれなかったため、想定していたプランを記載しています。)
transformation-plan.md
<!--
## Transformation Plan
### How to Modify This Plan
You can modify this transformation plan by editing the sections below. Here's what you can change:
**Step Descriptions**: Edit the text under each `## Step Name` to change what the step does
**Step Names**: Change the `## Step Name` headers to rename steps
**Add/Remove Steps**: Add new `## Step Name` sections or delete existing ones
**Substep Modifications**: Edit `### Substep Name` sections within each step
### Important Guidelines
1. **Keep the structure**: Maintain the `##` for main steps and `###` for substeps
2. **Be specific**: Provide clear, actionable descriptions for each step
3. **Reference files**: You can reference specific files or folders in your project
4. **Add examples**: Include code examples in your descriptions if helpful
Further Customization Steps (Optional)
1. Create a folder called "customTransformation" in your solution root directory (same level as your .sln file) - Only needed if you want to provide reference files
2. Put any supporting files you want the transformation to reference (code examples, git diffs, configuration files, reference implementations, etc.) in the folder
The following custom transformation is currently supported:
**Coding pattern** - Enforce coding styles or implement specific coding patterns
### Instructions
Provide detailed instructions in natural language in the customization section at the bottom and uncomment it. You can include examples or reference specific files for context (examples and file references are optional).
-->
# Objective
Here is a plan based on assessment of your WindowsFormsAppTransformTest solution to migrate it to .NET 10.0. The migration will involve project file transformation, configuration modernization, and package updates with granular substeps for individual component transformations. The scope includes transformation of the experimental WinForms project to .NET 10.0 compatible target with custom code modernizations. You can modify project target versions, remove transformation of certain projects.
## Structural Transformation
Transform project structure and configurations for target framework .NET 10.0 compatibility
### Transform WindowsFormsAppTransformTest WinForms project [Experimental]
Convert WindowsFormsAppTransformTest WinForms project to .NET 10.0 using experimental transformation
## Package Updates and Compatibility
Update third-party NuGet packages and dependencies to .NET 10.0 compatible versions
### Update MySqlConnector NuGet package
Transform MySqlConnector package to .NET 10.0 compatible version
## Customization
Apply customized transformation guided by the user
### Change using statements
Change all using statements in Repository.cs to remove curly braces {}.
Example transformation:
Before:
```csharp
using (var connection = new MySqlConnection(ConnectionString))
{
// Code logic here
}
```
After:
```csharp
using var connection = new MySqlConnection(ConnectionString);
```
### Change Repository
Change all methods in IRepository.cs and IUserForm.cs explicitly declare an access modifier.
Example transformation:
Before:
```csharp
List<UserModel> Select();
```
After:
```csharp
public List<UserModel> Select();
```
※ コレクション式の変換はステップとして認識されなかったので、実際にはtransformation-plan.mdに反映されていません。
### Using collection expressions
Using collection expressions in MockUserFactory's CreateMockUsers
Example transformation:
Before:
```csharp
var users = new List<UserModel>
{
new UserModel { Id = 1, Name = "Alice" },
new UserModel { Id = 2, Name = "Bob" },
new UserModel { Id = 3, Name = "Charlie" }
};
```
After:
```csharp
List<UserModel> users =
[
new UserModel { Id = 1, Name = "Alice" },
new UserModel { Id = 2, Name = "Bob" },
new UserModel { Id = 3, Name = "Charlie" }
];
```
また、slnファイルと同じ階層にcustomTransformationディレクトリを作成し、その配下に任意のファイルを配置することで、コンテキストとして読み込み、transformation-plan.mdに読み込んでくれます。

.NET10へのモダナイズが無事完了し、ジョブの実行も完了しました。しかし、カスタム変換の「Change using statements」「Change Repository」のジョブ自体は完了しませんでした。

結果
変換の結果、下記の構文を変換してくれました。
- ファイルスコープの名前空間
- null許容参照型への変換
- 非推奨メソッド・クラスの変換
- (new!)using ステートメントの変換

ジョブの完了を確認することはできませんでしたが、結果的にコード上ではusingステートメントが全て変換されていました。ファイルスコープの名前空間の利用も相まって、かなりネストが低くなり、可読性が上がりました。一方で、interfaceに修飾子を明示的に定義する修正は行われませんでした。
カスタマイズを試してみて
実は、transformation-plan.mdを幾度となく変えて実行してみたのですが、私の記載方法が悪かったのか、ジョブのステップとして認識されないことがほとんどでした。usingの変換も、実際にステップとして認識されましたが、プロンプトを3回ぐらい変えないと認識してくれなかった他、実際に変換されたとしてもジョブの完了自体は確認できませんでした。
デフォルトでコメントアウトされている書き方にいかに近づけるかがポイントなのではないかと感じています。
5. まとめ
今回はAWS Transformの新機能のtransformation-plan.mdによるカスタム変換を利用してみました。
実際に触ってみると、.NET 10へのモダナイズはしっかり対応できていた一方、カスタマイズ内容が反映されないことがかなり多かったです。usingのカスタマイズ内容を読み込ませるのにも一苦労しました。また、コード変換自体もジョブによって変換されなかったりと、まちまちでした。
よりカスタマイズした変換内容をある程度幅の利かせた表現でもステップとして認識されると、モダナイズ後の非推奨・警告対応もはかどるのではないかと思いました。今回プレビュー版でしたが、GA版にも期待ですね。
2026年1月現在では、AWS Transformはカスタム変換エージェント以外はすべて無料で利用できるサービスとなっています。皆さんもAWS Transform で.NETやSQL Serverのモダナイズを試してみてはいかがでしょうか!
余談
変換後のコードでPRを出したら、GitHub AppのAmazon Q Developerに.NET 10なんてないよと怒られてしまいました。こちらも.NET 10対応になるようにモダナイズしてほしいですね。

*1:https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/statements/using
*2:https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/interface
*3:https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/proposals/csharp-12.0/collection-expressions
*4:https://learn.microsoft.com/ja-jp/dotnet/api/system.security.permissions.securitypermission?view=windowsdesktop-9.0
*5:https://learn.microsoft.com/ja-jp/dotnet/api/system.threading.thread.abort?view=netframework-4.8
*6:https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/proposals/csharp-10.0/file-scoped-namespaces
*7:https://learn.microsoft.com/ja-jp/dotnet/csharp/nullable-references#nullable-context