Я пытаюсь использовать protobuf в проекте С#, используя protobuf-net, и мне интересно, как лучше всего организовать это в структуре проекта Visual Studio.
При ручном использовании инструмента протонов для генерации кода на С# жизнь кажется легкой, но она не чувствует себя хорошо.
Я хочу, чтобы файл .proto считался основным файлом исходного кода, генерируя файлы С# в качестве побочного продукта, но до того, как компилятор С# включится.
Возможные варианты:
- Пользовательский инструмент для проточных инструментов (хотя я не вижу, с чего начать)
- Шаг предварительной сборки (вызов протогена или пакетного файла, который делает это)
Я боролся с 2) выше, поскольку он продолжает давать мне "Система не может найти указанный файл", если я не использую абсолютные пути (и мне не нравится, чтобы проекты были явно расположены).
Есть ли соглашение (пока) для этого?
Edit: Основываясь на комментариях @jon, я повторил метод шага предварительной сборки и использовал это (расположение жестких дисков в настоящее время), используя пример адресной книги Google:
c:\bin\protobuf\protogen "-i:$(ProjectDir)AddressBook.proto"
"-o:$(ProjectDir)AddressBook.cs" -t:c:\bin\protobuf\csharp.xslt
Edit2: Принимая рекомендацию @jon по минимизации времени сборки, не обрабатывая файлы .proto, если они не изменились, я сбил базовый инструмент для проверки (это, вероятно, можно было бы расширить до полного инструмента Custom-Build):
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);
}
}
}
Моя команда pre-build теперь (все в одной строке):
$(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