クソダサいコードが出た。
成果物
CodeDOM
今回はこれを使ってソースコードファイルを出力してみる。内容は名前空間とクラスだけ。
プロジェクト
dotnet new console -o CodeDomProp cd CodeDomProp dotnet add package System.CodeDom
コード
Program.cs
using System; using System.IO; using System.CodeDom; using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Reflection; // TypeAttributes namespace CodeDomProp { class Program { static void Main(string[] args) { Generate(CreateCode()); } // ファイル出力 private static void Generate(CodeCompileUnit compileunit) { CSharpCodeProvider provider = new CSharpCodeProvider(); string sourceFile = @"Hello.cs"; using (StreamWriter sw = new StreamWriter(sourceFile, false)) { IndentedTextWriter tw = new IndentedTextWriter(sw, " "); provider.GenerateCodeFromCompileUnit(compileunit, tw, new CodeGeneratorOptions()); tw.Close(); } } // コード生成 private static CodeCompileUnit CreateCode() { CodeCompileUnit targetUnit = new CodeCompileUnit(); CodeNamespace samples = new CodeNamespace("MyNamespace"); samples.Imports.Add(new CodeNamespaceImport("System")); CodeTypeDeclaration targetClass = new CodeTypeDeclaration("MyClass"); targetClass.IsClass = true; targetClass.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed; samples.Types.Add(targetClass); targetUnit.Namespaces.Add(samples); return targetUnit; } } }
出力結果
Hello.cs
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ namespace MyNamespace { using System; public sealed class MyClass { } }
汚い……。以下のような不満点がある。
auto-generated
コメント不要using
とclass
の間になぜ2改行?{
が改行されていないpublic
,sealded
の順序が指定できない(そういうもの?)
以下のようなコードが欲しかったのに……。
using System; namespace MyNamespace { public sealed class MyClass { } }
参考
- https://docs.microsoft.com/ja-jp/dotnet/framework/reflection-and-codedom/generating-and-compiling-source-code-from-a-codedom-graph
- https://docs.microsoft.com/ja-jp/dotnet/framework/reflection-and-codedom/how-to-create-a-class-using-codedom
- CodeCompileUnit
分析
どうやら以下のようにusing
がnamespace
の中に入るようにしか書けないっぽい。見たことないよそんなコード……。
namespace 名前空間 { using System; }
ふつうは以下。dotnet new console -o 名前
でも以下のように出力される。
using System; namespace 名前空間 { }
その上、自動実装プロパティなども使えないとか。問題が多すぎて使う気になれない。
ちょっと躓いたこと
DLL参照を追加しないと以下のようなエラーになる。
error CS1069: 型名 'CodeCompileUnit' は名前空間 'System.CodeDom' に見つかりませんでした。この型はアセンブリ 'System.CodeDom, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' に転送されました。このアセンブリへの参照を追加することを検討してください。
DLL参照の追加は以下。
dotnet add package System.CodeDom
TypeAttributesはSystem.Reflection
をusing
でインポートすること。
所感
思った以上に残念。
気になったのは、ブロック開始{
の前に改行+インデントがあるかないか。私は無い派だったのだが、C#のdotnet new
や、VisualStudioなどの自動生成は皆、改行+インデントするものが出力されていた。
だからもういいやと諦めて改行する派に改宗しようと決心した。なのに、CodeDomでは逆に改行+インデントしないものが出力される……。クソが! 1字1句思い通りに書きたいんじゃ!
やはり自分の思い通りに動いてくれるコードジェネレータが欲しい。
CodeDOMは使うのやめよう。まだ仕様よく確認してないけど。以下の点だけで、もう思い通りのコードが書けないとわかったし。
- C#2.0以降の構文に非対応
using System;
などすべてnamespace
配下に書かねばならない
深く調査してまでして使う価値があるのか。調査するのも面倒。がんばって調査した結果、実現できないことが発覚したという屈辱を味わいたくない。それなら劣化車輪の再発明したい。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- SQLite 3.29.0 ※
- C# dotnet 3.0.100 ※
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux