記録を待つ力がないとき

多くのC#開発者は、C#6.0の主要なコンストラクターとレコードの出現を楽しみにしており、この機能がバージョン7に延期されたことに失望したと思います。 木曜日の終わり頃に、不変の型を持ちたいという欲求は、どうしても私の忍耐を克服し、それらを生成するユーティリティを書くことにしました。 誰が気にする-私は猫をお願いします。



問題の声明は非常に明確に見られ、記録には以下が含まれている必要があります。



一般的に、すべてはScalaのケースクラスのようなものです。

レコードを説明するために、わずかに単純化されたC#構文が使用されました。

namespace Records { using System; record Test { Int32 Id; String Name; Nullable<Decimal> Amount; } }
      
      





テキストの解析は、Nemerle.PEGを使用して実行されます。これは文法です:

 grammar { ANY = !['\u0000'..'\u001F'] !'\u007F' ['\u0000'..'\uFFFF']; ws : void = ("\r\n" / "\n" / "\r" / "\t" / ' ')*; letter = [Lu, Ll, Lt, Lm, Lo]; digit = ['0'..'9']; keyword = "using" / "record" / "namespace"; identifier : string = letter (letter / digit)*; path : string = identifier ("." identifier)*; genericTypeDefinition : string = identifier ws"<"ws (genericTypeDefinition / identifier)(ws","ws (genericTypeDefinition / identifier))* ws">"; property : PropertyDefinition = !keyword (genericTypeDefinition / identifier) ws identifier ws";"; properties : List[PropertyDefinition] = (ws property ws)+; import : ImportDefinition = "using" ws path";"; record : RecordDefinition = "record" ws identifier ws "{" ws property (ws property)* ws "}"; nmspace : NamespaceDefinition = "namespace" ws path ws "{" (ws import)* ws record (ws record)* ws "}" ws !ANY; }
      
      





結果のDOMパーサーに基づいて、CodeDOMを使用してC#ソースコードが生成され、CSharpCodeProviderを使用してアセンブリにコンパイルされます。



実装を簡単にするために、各ファイルに新しい名前空間を追加する必要があります(将来、この制限を削除する予定です)。 言語の残りの部分は柔軟であることが判明しました。名前空間は他のファイルにすぐにインポートでき、宣言された型は他のレコードのフィールド型としてすぐに使用できます。



簡単な使用例を示します。

次の内容でUnits.rcsファイルを作成します。

 namespace Units { using System; record Unit1 { Int32 Id; String Name; } record Unit2 { Int32 Id; Unit1 Unit; Decimal Amount; } }
      
      





Delivery.rscと同様に

 namespace Delivery { using System; using Units; record Address { String CityName; String Street; String House; } record Package { Address Destination; Unit2 Contents; } }
      
      





アセンブリを取得するには、次のコマンドを実行する必要があります。

 RecSharp -i Units.rcs Delivery.rcs -o Records.dll
      
      





その結果、プロジェクトに接続してオブジェクトを使用できるアセンブリが取得されます。

VisualStudioの拡張機能を使用して、T4などのソースを生成することもできます。

プロジェクトはここで感じることができます:

RecSharp

(リリースにはNemerleをインストールしたくない人のためのバイナリがあります)

VisualStudioの拡張機能:

RecSharp.VisualStudio

(繰り返しますが、リリースにはコンパイル済みの.vsixがあります)



将来、CodeDOMからRoslynに移行するかもしれませんが、最初のクイックルックの後、コード生成用のAPIはCodeDOMよりも複雑に見えます。



このユーティリティが誰かに役立つと嬉しいです。



All Articles