بروتوكول مخازن في مشاريع C# باستخدام protobuf-net - أفضل الممارسات رمز جيل

StackOverflow https://stackoverflow.com/questions/453820

سؤال

أحاول استخدام protobuf في مشروع C# باستخدام protobuf-net و أنا أتساءل ما هي أفضل طريقة لتنظيم هذا في Visual Studio هيكل المشروع.

عندما يدويا باستخدام protogen أداة لتوليد التعليمات البرمجية في C#, الحياة تبدو سهلة ولكنها لا يشعر الحق.

أود .بروتو ملف يعتبر المصدر الرئيسي رمز الملف, توليد C# ملفات المنتج من قبل, ولكن قبل برنامج التحويل البرمجي C# تتدخل.

خيارات يبدو أن:

  1. أداة مخصصة على بروتو أدوات (على الرغم من أنني لا يمكن أن نرى من أين تبدأ هناك)
  2. قبل بناء خطوة (الدعوة protogen أو دفعة الملف الذي يفعل ذلك)

عانيت 2) أعلاه كما باعطائي "يتعذر على النظام العثور على الملف المحدد" إلا إذا كنت تستخدم مسارات مطلقة (و لا مثل إجبار المشاريع صراحة تقع).

هل هناك اتفاقية (حتى الآن) من أجل هذا ؟


تحرير: استنادا إلى @جون تعليقات, أنا محاكمته قبل بناء خطوة طريقة استخدام هذا (protogen موقع ضمنية الآن) ، وذلك باستخدام Google عنوان الكتاب على سبيل المثال:

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

Edit2: أخذ @جون توصية للحد من بناء المرة من خلال عدم معالجة .بروتو الملفات إذا لم يتغير ، لقد طرقت معا أداة أساسية للتحقق بالنسبة لي (وهذا ربما يمكن أن تتوسع إلى العرف-بناء أداة):

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

قبل بناء الأوامر الآن (كل على سطر واحد):

$(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
هل كانت مفيدة؟

المحلول

امتدادا شون رمز ، يسرني أن أعلن أن protobuf-net الآن Visual Studio التكامل عن طريق أداة مخصصة.المثبت msi هو متاح من صفحة المشروع.المزيد من المعلومات الكاملة هنا: protobuf-net;الآن مع إضافة دلافين أوكرا.

Visual Studio with protobuf-net as a Custom Tool

نصائح أخرى

استدعاء ما قبل بناء خطوة ولكن باستخدام المشروع المتغيرات (مثل $(ProjectPath)) لإنشاء المطلقة أسماء الملفات دون وجود لهم في الواقع في الحل الخاص بك يبدو الرهان معقولة بالنسبة لي.

شيء واحد قد ترغب في النظر ، على أساس تجربتي الماضية مولدات كود:قد ترغب في كتابة المجمع protogen الذي يولد رمز إلى موقع مختلف ، ثم التحقق من ما إذا كانت التعليمات البرمجية التي تم إنشاؤها حديثا هو نفس القانون القديم, و لا الكتابة فوقه إذا كان الأمر كذلك.بهذه الطريقة Visual Studio سوف تدرك لا شيء تغير و لا قوة هذا المشروع إلى إعادة بنائها - وقد قطع بناء مرات بشكل كبير بالنسبة لي في الماضي.

بدلا من ذلك, يمكنك أن تبقي تجزئة md5 من .بروتو الملف آخر مرة protogen أعدم فقط تنفيذ protogen إذا .بروتو الملف قد تغير - حتى أقل من أن يفعل في كل بناء!

شكرا على رفع هذا السؤال على الرغم من ذلك - فإنه يشير بوضوح إلى أنني يجب أن تجد طريقة لجعل هذا سهلة قبل بناء خطوة بلدي الميناء.

إضافة التالية pre-build إلى إعدادات المشروع لتوليد ملف C# فقط عندما .بروتو الملف قد تغير.مجرد استبدال YourFile مع اسم من اسم قاعدة الخاص بك .بروتو الملف.

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 }

هذا يعمل في أي إصدار أحدث من Visual Studio, على عكس protobuf-صافي مخصص-بناء أداة التي لا تدعم 2012 Visual Studio أو Visual Studio 2013 ، وفقا القضايا 338 و 413.

هذا إضافة إلى المشاريع ذات الصلة الملف.

ميزة إضافية بناء.

العيب تحتاج إلى تحرير يدويا عند إضافة الملفات.

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

حسنا, هذا أعطاني فكرة (شيء عن إعادة اختراع العجلة)...

  • إنشاء بسيطة Makefile.mak ، شيء من هذا القبيل
.SUFFIXES : .cs .proto

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

(ومن الواضح أن لا ننسى أن استبدال مسارات protogen و csharp.xlst). هام - protogen\protogen.exe الأمر بدءا من علامة التبويب الشخصية ، وليس 8 المساحات

  • إذا كنت لا ترغب في تحديد الملفات المراد بناء كل وقت ، قد تستخدم شيئا مثل
.SUFFIXES : .cs .proto

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

وقد أرفقت سريعة وقذرة Visual Studio أداة مخصصة التفاف حول ProtoGen.exe مدونة جوجل صفحة هذه القضية (http://code.google.com/p/protobuf-net/issues/detail?id=39).هذا يجعل إضافة .بروتو الملفات إلى C# مشاريع سهلة للغاية.

انظر التمهيدي في المرفق لمزيد من المعلومات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top