Frage

Ich versuche, protobuf mithilfe von protobuf-net in einem C#-Projekt zu verwenden, und frage mich, wie ich dies am besten in einer Visual Studio-Projektstruktur organisieren kann.

Bei der manuellen Verwendung des Protogen-Tools zum Generieren von Code in C# scheint das Leben einfach zu sein, aber es fühlt sich nicht richtig an.

Ich möchte, dass die .proto-Datei als primäre Quellcodedatei betrachtet wird und als Nebenprodukt C#-Dateien generiert, jedoch bevor der C#-Compiler beteiligt wird.

Die Optionen scheinen zu sein:

  1. Benutzerdefiniertes Tool für Proto-Tools (obwohl ich nicht weiß, wo ich dort anfangen soll)
  2. Pre-Build-Schritt (Aufruf von Protogen oder einer Batch-Datei, die das erledigt)

Ich hatte Probleme mit 2) oben, da mir immer wieder die Meldung angezeigt wird, dass das System die angegebene Datei nicht finden kann, es sei denn, ich verwende absolute Pfade (und ich erzwinge nicht gerne, dass Projekte explizit lokalisiert werden).

Gibt es dafür (noch) eine Konvention?


Bearbeiten:Basierend auf den Kommentaren von @jon habe ich die Pre-Build-Schrittmethode erneut ausprobiert und diese verwendet (der Standort des Protogens ist vorerst fest codiert), wobei ich das Adressbuchbeispiel von Google verwendet habe:

c:\bin\protobuf\protogen "-i:$(ProjectDir)AddressBook.proto" 
       "-o:$(ProjectDir)AddressBook.cs" -t:c:\bin\protobuf\csharp.xslt

Edit2:Ich bin der Empfehlung von @jon gefolgt, die Build-Zeit dadurch zu minimieren, dass die .proto-Dateien nicht verarbeitet werden, wenn sie sich nicht geändert haben, und habe ein einfaches Tool zur Überprüfung für mich zusammengestellt (dieses könnte wahrscheinlich zu einem vollständigen Custom-Build-Tool erweitert werden):

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);
        }
    }
}

Mein Pre-Build-Befehl lautet jetzt (alles in einer Zeile):

$(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
War es hilfreich?

Lösung

Als Erweiterung von Shaun Code, ich bin froh, dass protobuf-net zu verkünden hat jetzt Visual Studio-Integration mittels eines Custom Tool. Das MSI-Installationsprogramm ist von der Projektseite . Ausführlichere Informationen hier: protobuf-net; jetzt mit zusätzlichen Orcas .

Visual Studio mit protobuf-net als ein Custom Tool

Andere Tipps

Der Aufruf einen Pre-Build-Schritt, aber unter Verwendung von Projektvariablen (z $(ProjectPath)) absoluten Dateinamen zu erstellen, ohne dass sie tatsächlich in Ihrer Lösung mit würde eine vernünftige Wette scheint mir.

Eine Sache, die Sie wollen vielleicht prüfen, basierend auf meinen Erfahrungen aus der Vergangenheit von Codegeneratoren: Sie möchten vielleicht einen Wrapper für Protogen schreiben, die Code an eine andere Stelle erzeugt, überprüft dann, ob die neu generierten Code der gleiche wie der alte ist Code und überschreibt nicht es, wenn so. Auf diese Weise Visual Studio wird nichts erkennen, hat sich verändert und nicht mit Gewalt das Projekt neu erstellt werden -. Hat diese geschnitten mal bauen dramatisch für mich in der Vergangenheit

Alternativ können Sie einen MD5-Hash des halten .proto das letzte Mal Protogen Datei ausgeführt wurde, und nur Protogen ausgeführt werden, wenn die .proto Datei geändert hat - noch weniger auf jeder bauen zu tun

Danke für dies als Frage aufwirft, obwohl - es zeigt eindeutig, soll mich einen Weg erarbeitet dies ein einfacher Pre-Build-Schritt für meinen eigenen Port machen

.

Fügen Sie das folgende Pre-Build-Ereignis zu den Projekteinstellungen der C # Datei nur dann zu erzeugen, wenn die .proto Datei geändert hat. Ersetzen Sie einfach YourFile mit dem Namen des Basis Namen Ihrer .proto Datei.

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 }

Dies funktioniert in jeder aktuellere Version von Visual Studio, im Gegensatz zu dem protobuf-net Benutzerdefinierte-Build-Tool, das nicht auf dem Visual Studio 2012 oder Visual Studio 2013, nach Themen: 338 und 413 .

Fügen Sie diese auf der jeweiligen Projektdatei.

Vorteil, schrittweise Entwicklung.

Nachteil, müssen Sie manuell bearbeiten, wenn Dateien hinzugefügt wird.

<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>

Nun ja, das brachte mich auf eine Idee (etwas darüber, das Rad neu zu erfinden) ...

  • Erstellen Sie ein einfaches Makefile.mak, so etwas wie
.SUFFIXES : .cs .proto

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

(Vergessen Sie natürlich nicht, die Pfade zu protogen und csharp.xlst zu ersetzen.) WICHTIG – Der Befehl protogen\protogen.exe beginnt mit dem Tabulatorzeichen, nicht mit 8 Leerzeichen

  • Wenn Sie nicht ständig Dateien angeben möchten, die erstellt werden müssen, können Sie so etwas wie verwenden
.SUFFIXES : .cs .proto

all: mycs1.cs myotherfile.cs

.proto.cs:
    protogen\protogen.exe -i:$? -o:$@ -t:protogen\csharp.xlst
  • im Pre-Build-Schritt zum Hinzufügen
cd $(ProjectDir) && "$(DevEnvDir)..\..\vc\bin\nmake" /NOLOGO -c -f Makefile.mak mycs1.cs myotherfile.cs

oder, wenn Sie nmake in Ihrem Pfad haben, können Sie eines verwenden

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

Ich habe einen schnellen und schmutzigen Visual Studio Custom Tool-Wrapper um ProtoGen.exe auf die Google-Code-Seite für dieses Problem ( http://code.google.com/p/protobuf-net/issues/detail?id=39 ). Dies macht das Hinzufügen .proto Dateien in C # -Projekten extrem einfach.

Sehen Sie die readme im Anhang für weitere Informationen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top