.net - ما هي الاختلافات بين AssemblyVersion و AssemblyFileVersion و AssemblyInformationalVersion؟


3 Answers

هنا هو آخر بلوق كتبت مؤخرا أن يتعمق في تفاصيل إصدار التجميع ...

يمكن أن يكون تعيين إصدار التجميعات في .NET احتمالًا مربكًا نظرًا لوجود ثلاث طرق على الأقل لتحديد إصدار للتجميع الخاص بك.

فيما يلي سمات التجميع الرئيسية الثلاثة المتعلقة بالإصدار:

// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

حسب الاصطلاح ، يشار إلى الأجزاء الأربعة من الإصدار بالإصدار الرئيسي والإصدار الثانوي والبناء والمراجعة .

المقصود AssemblyFileVersion تعريف فريد من إنشاء التجميع الفردية

عادةً ما تقوم يدويًا بتعيين الرئيسية و Minor AssemblyFileVersion لعكس إصدار التجميع ، ثم زيادة البناء و / أو المراجعة في كل مرة يقوم نظام الإنشاء الخاص بك بتصنيف التجميع. يجب أن تسمح لك AssemblyFileVersion بتعريف بنية التجميع بشكل فريد ، بحيث يمكنك استخدامها كنقطة بداية لتصحيح أي مشكلات.

في مشروعي الحالي لدينا خادم الإنشاء يشفر رقم changelist من مستودع مراقبة المصدر لدينا في أجزاء البناء والتنقيح من AssemblyFileVersion. هذا يسمح لنا بالتخطيط مباشرة من التجميع إلى شفرة المصدر الخاصة به ، لأي تجميع يتم إنشاؤه من قبل خادم الإنشاء (دون الحاجة إلى استخدام تسميات أو فروع في التحكم بالمصادر ، أو الاحتفاظ يدويًا بأي سجلات للنسخ التي تم إصدارها).

يتم تخزين رقم الإصدار هذا في مورد إصدار Win32 ويمكن رؤيته عند عرض صفحات خصائص مستكشف Windows للتجميع.

لا يهتم CLR ولا يفحص AssemblyFileVersion.

المقصود AssemblyInformationalVersion لتمثيل إصدار المنتج بأكمله

المقصود من AssemblyInformationalVersion هو السماح بإصدار متماسك للمنتج بأكمله ، والذي قد يتكون من العديد من التجميعات التي تم إصدارها بشكل مستقل ، ربما مع اختلاف سياسات إصدار الإصدارات ، وربما تكون قد تم تطويرها بواسطة فرق مختلفة.

"على سبيل المثال ، قد يحتوي الإصدار 2.0 من منتج على عدة تجميعات؛ تم وضع علامة على أحد هذه التجميعات كإصدار 1.0 حيث إنه تجميع جديد لم يتم شحنه في الإصدار 1.0 من نفس المنتج. عادة ، يمكنك تعيين الأجزاء الرئيسية والثانوية من رقم الإصدار هذا لتمثيل الإصدار العام لمنتجك. ثم تقوم بزيادة أجزاء الإنشاء والمراجعة في كل مرة تقوم فيها بتجميع منتج كامل مع جميع تجميعاته. "- جيفري ريختر ، CLR عبر C # (الإصدار الثاني) p. 57

لا يهتم CLR ولا يفحص AssemblyInformationalVersion.

إن AssemblyVersion هو الإصدار الوحيد الذي يهتم به CLR (لكنه يهتم بكامل AssemblyVersion )

يتم استخدام AssemblyVersion بواسطة CLR لربط التجميعات المسماة بشدة. يتم تخزينها في جدول بيانات التعريف الخاص التجميع AssemblyDef التجميع المبني وفي جدول AssemblyRef أي التجميع الذي يشير إليها.

هذا مهم جداً ، لأنه يعني أنه عند الإشارة إلى تجميع مسمى بشدة ، فأنت ملزم بشدة إلى AssemblyVersion معينة من ذلك التجميع. يجب أن يكون assemblyVersion بأكمله تطابق تام لنجاح الربط. على سبيل المثال ، إذا قمت بالإشارة إلى الإصدار 1.0.0.0 من تجميع مسمى بقوة في وقت الإنشاء ، ولكن الإصدار 1.0.0.1 من ذلك التجميع متاح في وقت التشغيل ، فسوف يفشل الربط! (عندها يجب عليك العمل حول هذا باستخدام التجميع Binding Redirection .)

الارتباك حول ما إذا كان يجب أن يتوافق مع AssemblyVersion بأكمله. (نعم إنها كذلك.)

هناك بعض الارتباك حول ما إذا كان يجب أن يكون assemblyVersion بأكمله تطابق تام لكي يتم تحميل تجميع. بعض الناس تحت الإيمان الكاذب بأن الأجزاء الرئيسية والقصيرة من AssemblyVersion يجب أن تتطابق لكي ينجح الارتباط. هذا افتراض معقول ، ومع ذلك فهو غير صحيح في نهاية المطاف (اعتبارًا من .NET 3.5) ، ومن المفيد التحقق من ذلك لإصدار CLR الخاص بك. فقط تنفيذ هذا نموذج التعليمة البرمجية .

على الجهاز الخاص بي فشل تحميل التجميع الثاني ، والخطين الأخيرين من سجل الانصهار يجعل من الواضح تماما لماذا:

.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for  failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, 
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition 
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'

=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
 (Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

أعتقد أن مصدر هذا الارتباك ربما يرجع إلى أن Microsoft كانت تهدف أصلاً إلى أن تكون أكثر تساهلاً مع هذه المطابقة الصارمة لـ AssemblyVersion الكاملة ، من خلال التطابق فقط مع أجزاء الإصدار الرئيسية والرائدة:

"عند تحميل تجميع ، سيعثر CLR تلقائيًا على أحدث إصدار خدمة مثبت يطابق الإصدار الرئيسي / الثانوي للتجميع المطلوب." - Jeffrey Richter، CLR via C # (Second Edition) p. 56

كان هذا هو السلوك في Beta 1 من 1.0 CLR ، ولكن تمت إزالة هذه الميزة قبل الإصدار 1.0 ، ولم تتم إعادة التسيير في .NET 2.0:

"ملاحظة: لقد وصفت للتو كيف يجب أن تفكر في أرقام الإصدارات. لسوء الحظ ، لا يعامل CLR أرقام الإصدارات بهذه الطريقة. [في .NET 2.0] ، يعامل CLR رقم إصدار كقيمة معتمة ، وإذا اعتمد تجميع على الإصدار 1.2.3.4 من تجميع آخر ، يحاول CLR تحميل الإصدار 1.2.3.4 فقط (ما لم يكن هناك إعادة توجيه ربط في مكان ). ومع ذلك ، لدى Microsoft خطط لتغيير محمل CLR في إصدار مستقبلي بحيث يقوم بتحميل أحدث إصدار / مراجعة لإصدار رئيسي / ثانوي محدد من تجميع . على سبيل المثال ، في إصدار مستقبلي من CLR ، إذا كان المحمل يحاول العثور على الإصدار 1.2.3.4 من التجميع والإصدار 1.2.5.0 ، فإن المحمل يقوم تلقائيًا باختيار أحدث إصدار للخدمة. سيكون هذا تغييرًا مرحبًا جدًا بمحمل CLR - أنا لا أستطيع الانتظار. - جيفري ريختر ، CLR عبر C # (الإصدار الثاني) p. 164 (منجم التشديد)

نظرًا لأن هذا التغيير لم يتم تنفيذه بعد ، أعتقد أنه من الآمن افتراض أن Microsoft قد تعيدت تتبع هذا النوايا ، وربما فات الأوان لتغيير هذا الآن. حاولت البحث عبر الويب لمعرفة ما حدث مع هذه الخطط ، ولكن لم أجد أي إجابات. ما زلت أرغب في الوصول إلى الجزء السفلي منه.

لذلك بعثت بالبريد الإلكتروني جيف ريختر وسألته مباشرة - فكنت أحسب ما إذا كان أي شخص يعرف ما حدث ، فستكون له.

أجاب في غضون 12 ساعة ، في صباح يوم السبت على أقل تقدير ، وأوضح أن محمل. NET 1 Beta 1 نفذت هذه الآلية 'التلقائية إلى الأمام' من التقاط أحدث البناء ومراجعة التجميع ، ولكن هذا السلوك كان عادت قبل .NET 1.0 شحنها. وكان الهدف من ذلك لاحقًا هو إحياء ذلك ، ولكن لم يتم إدخاله قبل شحن CLR 2.0. ثم جاء سيلفرلايت ، الذي حظي بالأولوية لفريق CLR ، لذا تأخرت هذه الوظيفة أكثر. في هذه الأثناء ، انتقل معظم الأشخاص الذين كانوا موجودين في أيام CLR 1.0 Beta 1 منذ ذلك الحين ، لذا فمن غير المرجح أن يشهد ذلك ضوء النهار ، على الرغم من كل العمل الشاق الذي تم بالفعل وضعه فيه.

يبدو أن السلوك الحالي هو البقاء هنا.

تجدر الإشارة أيضًا من نقاشي مع جيف إلى أن AssemblyFileVersion قد تمت إضافته فقط بعد إزالة آلية "التلقائية إلى الأمام" - لأنه بعد الإصدار 1.0 Beta 1 ، كان أي تغيير في AssemblyVersion بمثابة تغيير مفاجئ لعملائك ، فكان هناك مكان لتخزين بأمان رقم البناء الخاص بك بأمان. AssemblyFileVersion هو ذلك الملاذ الآمن ، حيث لا يتم فحصه تلقائيًا بواسطة CLR. ربما يكون أكثر وضوحًا بهذه الطريقة ، وجود رقمين منفصلين للإصدار ، مع معان منفصلة ، بدلاً من محاولة جعل هذا الفصل بين Major / Minor (الكسر) وأجزاء Build / Revision (غير التالفة) لـ AssemblyVersion.

خلاصة القول: فكر جيدًا عند تغيير AssemblyVersion

المعنى الأخلاقي هو أنه إذا كنت تقوم بشحن تجميعات سيقوم المطورون الآخرون بتحديدها ، فيجب أن تكون حذراً للغاية عندما تقوم بذلك (ولا تفعل) تغيير AssemblyVersion لهذه التجميعات. ستعني أية تغييرات في AssemblyVersion أن مطوري التطبيقات سيحتاجون إما إلى إعادة ترجمة مقابل الإصدار الجديد (لتحديث إدخالات AssemblyRef) أو استخدام عمليات إعادة توجيه تجليد التجميع لتجاوز التجليد يدويًا.

  • لا تقم بتغيير AssemblyVersion لإصدار الخدمة الذي يهدف إلى أن يكون متوافقًا للخلف.
  • قم بتغيير AssemblyVersion للإصدار الذي تعرف أنه يحتوي على تغييرات متكررة.

ما عليك سوى إلقاء نظرة أخرى على سمات الإصدار على mscorlib:

// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]

لاحظ أنه ملف AssemblyFileVersion الذي يحتوي على كافة معلومات الخدمة المثيرة للاهتمام (إنه جزء المراجعة من هذا الإصدار الذي يخبرك بما تقوم بتشغيله Service Pack) ، وفي هذه الأثناء يتم تثبيت AssemblyVersion في 2.0.0.0 قديمًا مملاً. أي تغيير في AssemblyVersion سيفرض كل تطبيق .NET الرجوع إلى mscorlib.dll لإعادة ترجمة مقابل الإصدار الجديد!

Question

هناك ثلاث سمات نسخة التجميع. ما هي الاختلافات؟ هل هو موافق إذا كنت تستخدم AssemblyVersion وتجاهل الباقي؟

MSDN يقول:

  • AssemblyVersion :

    يحدد إصدار التجميع الذي يتم نسبه.

  • AssemblyFileVersion :

    لتوجيه مترجم لاستخدام رقم إصدار محدد لمورد إصدار الملف Win32. إصدار الملف Win32 غير مطلوب ليكون نفس رقم إصدار التجميع.

  • AssemblyInformationalVersion :

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

هذا هو متابعة ما هي أفضل الممارسات لاستخدام سمات التجميع؟




يتم عرض AssemblyInformationalVersion و AssemblyFileVersion عند عرض معلومات "الإصدار" على ملف من خلال مستكشف Windows عن طريق عرض خصائص الملف. هذه السمات في الواقع الحصول على ترجمة في مورد VERSION_INFO الذي يتم إنشاؤه بواسطة برنامج التحويل البرمجي.

AssemblyInformationalVersion هي قيمة "إصدار المنتج". AssemblyFileVersion هي قيمة "إصدار الملف".

AssemblyVersion خاصة التجميعات .NET ويستخدم من قبل محمل تجميع .NET لمعرفة إصدار التجميع لتحميل / ربط في وقت التشغيل.

خارج هذه ، هو الوحيد المطلوب بشكل كامل بواسطة .NET السمة AssemblyVersion . لسوء الحظ ، يمكن أن يتسبب أيضًا في معظم المشاكل عندما يتغير بشكل عشوائي ، خاصةً إذا كنت تقوم بتسمية التجميعات الخاصة بك.




للحفاظ على هذا السؤال الحالي ، تجدر الإشارة إلى أن AssemblyInformationalVersion تستخدمه NuGet وتعكس إصدار الحزمة بما في ذلك أي لاحقة مسبقة.

على سبيل المثال AssemblyVersion من 1.0.3. * تعبئتها مع aspnet core dotnet-cli

dotnet pack --version-suffix ci-7 src/MyProject

ينتج حزمة مع الإصدار 1.0.3-ci-7 والتي يمكنك فحصها باستخدام الانعكاس باستخدام:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);



Related