16

protobuf-net を使用して、C# プロジェクトで protobuf を使用しようとしていますが、これを Visual Studio プロジェクト構造に編成する最良の方法は何か疑問に思っています。

protogen ツールを手動で使用してコードを C# に生成する場合、人生は簡単に思えますが、正しくないと感じます。

.proto ファイルを主要なソース コード ファイルと見なし、C# コンパイラが関与する前に副産物として C# ファイルを生成したいと考えています。

オプションは次のようです。

  1. プロト ツール用のカスタム ツール (ただし、どこから始めればよいかわかりません)
  2. ビルド前のステップ (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
4

6 に答える 6

8

Shaun のコードの拡張として、protobuf-net がカスタム ツールを介して Visual Studio と統合されたことを発表できることをうれしく思います。msi インストーラーは、プロジェクト ページから入手できます。ここでより完全な情報: protobuf-net; Orcas が追加されました。

カスタム ツールとして protobuf-net を使用する Visual Studio

于 2009-07-16T18:06:36.723 に答える
8

ビルド前のステップを呼び出しますが、プロジェクト変数 (例: $(ProjectPath)) を使用して絶対ファイル名を作成し、実際にはソリューションに含める必要はありません。

私の過去のコード ジェネレーターの経験に基づいて、考慮すべきことの 1 つは、コードを別の場所に生成し、新しく生成されたコードが古いコードと同じかどうかをチェックする protogen のラッパーを作成することです。その場合は上書きしません。そうすれば、Visual Studio は何も変更されていないことを認識し、そのプロジェクトを強制的に再構築することはありません。これにより、過去にビルド時間が劇的に短縮されました。

あるいは、protogen が最後に実行されたときに .proto ファイルの md5 ハッシュを保持し、.proto ファイルが変更された場合にのみ protogen を実行することもできます。

ただし、これを質問として提起してくれてありがとう-これは、自分のポートの簡単なビルド前のステップにする方法を考え出す必要があることを明確に示唆しています.

于 2009-01-17T19:06:34.320 に答える
6

これを関連するプロジェクト ファイルに追加します。

アドバンテージ、インクリメンタル ビルド。

欠点は、ファイルを追加するときに手動で編集する必要があることです。

<ItemGroup>
    <Proto Include="Person.proto" />
    <Compile Include="Person.cs">
        <DependentUpon>Person.proto</DependentUpon>
    </Compile>
</ItemGroup>
<PropertyGroup>
    <CompileDependsOn>ProtobufGenerate;$(CompileDependsOn)</CompileDependsOn>
</PropertyGroup>
<Target Name="ProtobufGenerate" Inputs="@(Proto)" Outputs="@(Proto->'$(ProjectDir)%(Filename).cs')">
    <ItemGroup>
        <_protoc Include="..\packages\Google.Protobuf.*\tools\protoc.exe" />
    </ItemGroup>
    <Error Condition="!Exists(@(_protoc))" Text="Could not find protoc.exe" />
    <Exec Command="&quot;@(_protoc)&quot; &quot;--csharp_out=$(ProjectDir.TrimEnd('\'))&quot; @(Proto->'%(Identity)',' ')" WorkingDirectory="$(ProjectDir)" />
</Target>
于 2015-09-17T19:50:48.227 に答える
6

次のビルド前イベントをプロジェクト設定に追加して、.proto ファイルが変更された場合にのみ C# ファイルを生成します。YourFile.proto ファイルのベース名の名前に置き換えるだけです。

cd $(ProjectDir) && powershell -Command if (!(Test-Path YourFile.proto.cs) -or (Get-Item YourFile.proto).LastWriteTimeUtc -gt (Get-Item YourFile.proto.cs).LastWriteTimeUtc) { PathToProtoGen\protogen -i:YourFile.proto -o:YourFile.proto.cs }

これは、問題338および413によると、Visual Studio 2012 または Visual Studio 2013 をサポートしない protobuf-net Custom-Build ツールとは異なり、Visual Studio の最近のバージョンで機能します。

于 2012-12-13T08:52:12.963 に答える
5

まあ、それは私にアイデアを与えました(車輪の再発明についての何か)...

  • 次のような単純な Makefile.mak を作成します。
.SUFFIXES : .cs .proto

.proto.cs:
    protogen\protogen.exe -i:$? -o:$@ -t:protogen\csharp.xlst

(明らかに、protogen と csharp.xlst へのパスを置き換えることを忘れないでください)。重要 - protogen\protogen.exe コマンドは、8 つのスペースではなく、TAB 文字で始まります

  • 常にビルドする必要があるファイルを指定したくない場合は、次のようなものを使用できます
.SUFFIXES : .cs .proto

すべて: mycs1.cs myotherfile.cs

.proto.cs:
    protogen\protogen.exe -i:$? -o:$@ -t:protogen\csharp.xlst
  • 追加するビルド前のステップで
cd $(ProjectDir) && "$(DevEnvDir)..\..\vc\bin\nmake" /NOLOGO -c -f Makefile.mak mycs1.cs myotherfile.cs

または、パスに nmake がある場合は、次を使用できます

cd $(ProjectDir) && nmake /NOLOGO -c -f Makefile.mak mycs1.cs myotherfile.cs

于 2009-05-22T00:44:05.607 に答える
2

この問題の Google Code ページ ( http://code.google.com/p/protobuf-net/issues/detail?id=39 )に、ProtoGen.exe のクイックで汚れた Visual Studio カスタム ツール ラッパーを添付しました。これにより、C# プロジェクトへの .proto ファイルの追加が非常に簡単になります。

詳細については、添付の readme を参照してください。

于 2009-06-24T18:02:25.807 に答える