protobuf-net を使用して、C# プロジェクトで protobuf を使用しようとしていますが、これを Visual Studio プロジェクト構造に編成する最良の方法は何か疑問に思っています。
protogen ツールを手動で使用してコードを C# に生成する場合、人生は簡単に思えますが、正しくないと感じます。
.proto ファイルを主要なソース コード ファイルと見なし、C# コンパイラが関与する前に副産物として C# ファイルを生成したいと考えています。
オプションは次のようです。
- プロト ツール用のカスタム ツール (ただし、どこから始めればよいかわかりません)
- ビルド前のステップ (protogen またはそれを実行するバッチ ファイルの呼び出し)
絶対パスを使用しない限り、「システムは指定されたファイルを見つけることができません」と表示されるため、上記の2)に苦労しました(また、プロジェクトを明示的に配置することを強制したくありません)。
これには(まだ)慣習がありますか?
編集: @jon のコメントに基づいて、ビルド前のステップ メソッドを再試行し、Google のアドレス帳の例を使用して、これを使用しました (プロトジェンの場所は今のところハードコードされています)。
c:\bin\protobuf\protogen "-i:$(ProjectDir)AddressBook.proto"
"-o:$(ProjectDir)AddressBook.cs" -t:c:\bin\protobuf\csharp.xslt
Edit2: .proto ファイルが変更されていない場合は処理しないことでビルド時間を最小限に抑えるという @jon の推奨事項を取り入れて、チェックするための基本的なツールをまとめました (これはおそらく完全なカスタム ビルド ツールに拡張できます)。 ):
using System;
using System.Diagnostics;
using System.IO;
namespace PreBuildChecker
{
public class Checker
{
static int Main(string[] args)
{
try
{
Check(args);
return 0;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return 1;
}
}
public static void Check(string[] args)
{
if (args.Length < 3)
{
throw new ArgumentException(
"Command line must be supplied with source, target and command-line [plus options]");
}
string source = args[0];
string target = args[1];
string executable = args[2];
string arguments = args.Length > 3 ? GetCommandLine(args) : null;
FileInfo targetFileInfo = new FileInfo(target);
FileInfo sourceFileInfo = new FileInfo(source);
if (!sourceFileInfo.Exists)
{
throw new ArgumentException(string.Format(
"Source file {0} not found", source));
}
if (!targetFileInfo.Exists ||
sourceFileInfo.LastWriteTimeUtc > targetFileInfo.LastAccessTimeUtc)
{
Process process = new Process();
process.StartInfo.FileName = executable;
process.StartInfo.Arguments = arguments;
process.StartInfo.ErrorDialog = true;
Console.WriteLine(string.Format(
"Source newer than target, launching tool: {0} {1}",
executable,
arguments));
process.Start();
}
}
private static string GetCommandLine(string[] args)
{
string[] arguments = new string[args.Length - 3];
Array.Copy(args, 3, arguments, 0, arguments.Length);
return String.Join(" ", arguments);
}
}
}
私のビルド前のコマンドは次のとおりです(すべて1行で):
$(SolutionDir)PreBuildChecker\$(OutDir)PreBuildChecker
$(ProjectDir)AddressBook.proto
$(ProjectDir)AddressBook.cs
c:\bin\protobuf\protogen
"-i:$(ProjectDir)AddressBook.proto"
"-o:$(ProjectDir)AddressBook.cs"
-t:c:\bin\protobuf\csharp.xslt