そこでVisual Studio 2015以降ではコンパイラー基盤がRoslynになっているのでそれを使えばいいのではというのが今回のアイデアです。
T4の中でRoslynを使ってコードを読み込む
さてどうやってRoslynを使って読み込むのかという話ですが、残念なことにVisual Studio 2015の内部で「現在動いているRoslynのインスタンス」に直接アクセスすることはできません。
ですが、Visual Studio 2015に含まれているRoslynを使うことはできます。Roslynは C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies におかれているので、それらしいアセンブリを参照して名前空間をインポートします。
voidMain() { // 対象となるプロジェクトの.csprojのパス var projPath = @"C:\Users\Tomoyo\Documents\visual studio 2015\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.csproj"; var classNames = GetClassNamesAsync(projPath).Result; classNames.Dump(); }
// Roslynを使ってプロジェクトのコードからクラスのコンストラクタ定義を引っこ抜く async Task<List<string>> GetClassNamesAsync(string csprojPath) { // MSBuildのワークスペース(環境みたいなもの)を作って、プロジェクトファイルを開く var workspace = MSBuildWorkspace.Create(); var project = await workspace.OpenProjectAsync(csprojPath);
// ソースコードをコンパイル的なことをする(出力するわけではなくて内部的なデータを作るやつ) // これでコードをパースした結果を得ることができるようになる var compilation = await project.GetCompilationAsync();
var classNames = new List<string>(); // シンタックスツリーをファイル単位で適当になめていく foreach (var syntaxTree in compilation.SyntaxTrees) { // セマンティックモデル(シンタックスツリーは文法で、それに対応する「コード的な意味」)を取得する var semModel = compilation.GetSemanticModel(syntaxTree);
// Roslynを使ってプロジェクトのコードからクラスのコンストラクタ定義を引っこ抜く async Task<List<string>> GetClassNamesAsync(string csprojPath) { // MSBuildのワークスペース(環境みたいなもの)を作って、プロジェクトファイルを開く var workspace = MSBuildWorkspace.Create(); var project = await workspace.OpenProjectAsync(csprojPath);
// ソースコードをコンパイル的なことをする(出力するわけではなくて内部的なデータを作るやつ) // これでコードをパースした結果を得ることができるようになる var compilation = await project.GetCompilationAsync();
var classNames = new List<string>(); // シンタックスツリーをファイル単位で適当になめていく foreach (var syntaxTree in compilation.SyntaxTrees) { // セマンティックモデル(シンタックスツリーは文法で、それに対応する「コード的な意味」)を取得する var semModel = compilation.GetSemanticModel(syntaxTree);