ساخت پکیج های Nuget با نسخه های مختلف NET.

ساخت پکیج ها برای یک نسخه از .net بسیار ساده است و به خوبی مستند شده است. اما درخواست بعدی چیست؟ آیا می توانیم آن را برای همه نسخه های .NET 4.5.2 به 4.6.1 و یا قدیمی ترNET 4.7 به روز رسانی کنیم؟

ساخت  پکیج های Nuget با نسخه های مختلف NET.

بیش از 200 پروژه وجود دارد که با نسخه های مشابه .NET منتشر شده است. بنابراین باز کردن هر پروژه و تغییر نسخه آن و کامپایل کردن، گزینه مناسبی نیست.

<PropertyGroup>
   <Configuration Condition=" '$(Configuration)' == '' 
   ">Debug</Configuration>
   <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
   <ProjectGuid>{21E95439-7A66-4C75-ACC5-1B9A5FF4A32D}</ProjectGuid>
   <OutputType>Library</OutputType>
   <AppDesignerFolder>Properties</AppDesignerFolder>
   <RootNamespace>MyProject.Clients</RootNamespace>
   <AssemblyName>MyProject.Clients</AssemblyName>
   <span style="background-color:#ffff00;">
   <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</span>   <FileAlignment>512</FileAlignment>
   <TargetFrameworkProfile />
</PropertyGroup>

با بررسی فایل های .csproj توجه کنید که داخل تگ <TargetFrameworkVersion> یک نسخه .NET است. زمانی که آن را تغییر می دهید، در خاصیت .NET version بصورت موثر تغییر می کند. بنابراین خیلی ساده است: با استفاده از یک ویرایشگر متن ساده به نام Notepad++، همه فایل های .csproj را جایگذاری کنید و مجددا آن را کامپایل نمایید. این کار می کند اما ...

درباره پکیج Nuget

به عنوان مثال پروژه ای ساختیم که برای نسخه .NET 4.5.2 بوده اما نسخه کنونی .NET 4.6.1 است. بنابراین این مورد بهینه نیست و احتمالا به درستی با یکدیگر پیوند داده نمی شوند. بنابراین با به روز رسانی پکیج های Nuget که شامل هر دو نسخه است مواجه می شویم. روشی که بتواند به توسعه دهندگانی که در نسخه 4.5.2 هستند با کسانی که به روز هستند کمک کنیم چیست؟ آیا مشکل حل می شود؟ اما چطور؟

آیا این موضوع می تواند بصورت خودکار درست شود؟

ساخت پکیج های Nuget

تکنیک پیش نیاز

ابتدا آخرین نسخه Nuget را از nuget.org/downloads دانلود کنید، آن را در مسیر مورد نظر ذخیره کنید. سپس به مسیر یک متغیر PATH environment به ویندوز اضافه کنید اگر بصورت خودکار ساخته نشده است.

نکته: nuget.exe یک ابزار CLI است نه یک نصب کننده، بنابراین مطمئن شوید که فایل دانلود شده را قبل از اجرا ذخیره کنید.

ما در این فایل کپی کردیم، C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7Tools، همچنین در متغیر PATH environment سیستم عامل نیز وجود دارد. اکنون ما دسترسی داریم به CLI از هرجای سیستم عامل که بخواهیم.

خیلی خوب است که داشته باشیم

https://github.com/NuGetPackageExplorer/NuGetPackageExplorer

Explorer یک برنامه شکلاتی و یک بار کلیک است که باعث می شود به راحتی آن را بسازید و با آن کار کنید. بعد از نصب آن، دو بار بر روی فایل .nupkg کلیک کنید برای دیدن محتوا پکیج، یا شما می توانید پکیج را بارگذاری کنید دقیقا در nuget.org یا روی Nuget Server شخصی خودتان.

این ابزار ارزشمند ثابت خواهد کرد که شما در حال ساخت کارهای عجیب و غریب تری هستید.

پیش نیاز یک پکیج خوب

اسمبلی ( یا مجموعه ای از اسمبلی ها) یک کاندیدای خوب برای یک بسته است و دارای کمترین وابستگی ممکن است. به عنوان مثال، یک پکیج logging فقط کار logging را انجام می دهد نه چیزی بیشتر. مشابه آن، پکیج Nuget می تواند هر جایی استفاده شود، بدون استفاده از شرط های خاصی. زمانی که وابستگی ها مورد نیاز است، سپس آن ها ترجیحا در پکیج های دیگری از Nuget هستند.

ساخت یک پکیج

در ویژوال استادیو، ساخت پروژه انتخاب شماست. مطمئن شوید آن را کامپایل کنید.

اکنون Dev command prompt و وارد آن شوید...

nuget spec

این یک قالب به نام .nuspec تولید می کند که شامل نقطه آغازین شما است. مثالی از فایل .nuspec

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
   <metadata>
       <!-- The identifier that must be unique within the hosting gallery -->
       <id>Diagnostics.Logging</id>

       <!-- The package version number that is used when resolving dependencies -->
       <version>1.1.0</version>

       <!-- Authors contain text that appears directly on the gallery -->
       <authors>Gaston</authors>

       <!-- Owners are typically nuget.org identities that allow gallery
                 users to early find other packages by the same owners.   -->
       <owners>Gaston</owners>

       <!-- License and project URLs provide links for the gallery -->
<!--
       <licenseUrl>http://opensource.org/licenses/MS-PL</licenseUrl>
       <projectUrl>http://github.com/contoso/UsefulStuff</projectUrl>
-->
       <!-- The icon is used in Visual Studio's package manager UI -->
<!--
       <iconUrl>http://github.com/contoso/UsefulStuff/nuget_icon.png</iconUrl>
-->
       <!-- If true, this value prompts the user to accept the license when
                 installing the package. -->
       <requireLicenseAcceptance>false</requireLicenseAcceptance>

       <!-- Any details about this particular release -->
       <releaseNotes>Added binaries for .NET 4.6.1</releaseNotes>

       <!-- The description can be used in package manager UI. Note that the
                 nuget.org gallery uses information you add in the portal. -->
       <description>Logging base class </description>
       <!-- Copyright information -->
       <copyright>Copyright  ©2017</copyright>

       <!-- Tags appear in the gallery and can be used for tag searches -->
       <tags>diagnostics logging</tags>

       <!-- Dependencies are automatically installed when the package is installed -->
       <dependencies>
           <!--<dependency id="EntityFramework" version="6.1.3" />-->
       </dependencies>
   </metadata>

   <!-- A readme.txt will be displayed when the package is installed -->
   <!--
   <files>
       <file src="readme.txt" target="" />
   </files>
   -->
</package>

در پوشه پروژه و یک پکیج nuget آن را برای شما تولید می کند.

بررسی بسته بندی

اگر می خواهید بدانید که محتوا داخل پروژه صحیح است یا خیر از Nuget Package Explorer استفاده کنید و آن را باز کنید توسط Nuget Package Explorer.

در اینجا پکیجی را مشاهده می کنید که ما ساختیم. آن شامل مقداری meta data در سمت چپ است و پکیج در 2 نسخه در سمت راست. شما می توانید از این ابزار استفاده کنید و پوشه های بیشتری به ان اضافه نمایید برای تغییر متا دیتا. این بسیار خوب و جالب است اما خیلی خودکار نیست. برای مثال چگونه می توانیم یک پکیج nuget بسازیم مشابه این که شامل دو نسخه .NET باشد؟

سازماندهی پوشه

ما می خواهیم پکیج ها را جدا کنیم از بقیه پروسه ساخت. بنابراین یک پوشه Nuget در پروژه می سازیم.

فایل .nuspec را در داخل این پوشه انتقال می دهیم. برای داشتن یک نقطه آغازین و سپس یک فایل batch می سازیم که مشکلات زیر را حل کند.

1. ساخت پوشه های مورد نیاز

2. ساخت باینری های .NET 4.5.2

3. ساخت باینری های .NET 4.6.2

4. پکیج کردن مجموعه ای از باینری ها در Nuget Package

ما همچنین می خواهیم کاری کنیم که تنظیمات این پکیج نیز ساده باشد، بنابراین با استفاده از مقداری متغیر:

 Script

مقدار دهی متغیر ها

set ProjectLocation=C:\_Projects\Diagnostics.Logging
set Project=Diagnostics.Logging

set NugetLocation=%ProjectLocation%\NuGet\lib
set ProjectName=%Project%.csproj
set ProjectDll=%Project%.dll
set ProjectNuspec=%Project%.nuspec
set BuildOutputLocation=%ProjectLocation%\NuGet\temp

set msbuild="C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe"
set nuget="C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\nuget.exe"

2 متغیر اول پارامتر های واقعی است. همه متغیر های دیگر توسط این دو متغیر ساخته می شوند.

%msbuild% و %nuget% متغیر هایی هستند که به ما اجازه اجرا آسان command را می گیرند بدون تغییر مسیر. با تشکر از این دو خط، این اسکریپت در هر Dos prompt ای کار می کند. نه فقط در ویژوال استادیو یا command promopt

تنظیم ساختار پوشه ها

cd /d %ProjectLocation%\NuGet
md temp
md lib\lib\net452
md lib\lib\net461
copy /Y %ProjectNuspec% lib
copy /Y readme.txt lib

در فایل batch، ما به پوشه های موجود اعتماد نمی کنیم. بنابراین آن را هربار در پروژه می سازیم. ما می دانیم که ما می توانیم اول تست کنیم اگر پروژه وجود داشت بعدا آن را بساز اما نتیجه در انتها یکی می شود.

نکته اینجاست که ما Lib/Lib ساختیم. سطح اول شامل فایل های housekeeping است برای ساخت پکیج، سطح دوم شامل محتوایی است که ما می خواهیم در پکیج قرار دهیم.

ساخت پروژه درست در نسخه .NET

%msbuild% "%ProjectLocation%\%ProjectName%" 
/t:Clean;Build /nr:false /p:OutputPath="%BuildOutputLocation%";
Configuration="Release";
Platform="Any CPU";TargetFrameworkVersion=v4.5.2
copy /Y "%BuildOutputLocation%"\%ProjectDll% 
"%NugetLocation%"\lib\net452\%ProjectDll%

%msbuild% "%ProjectLocation%\%ProjectName%" 
/t:Clean;Build /nr:false /p:OutputPath="%BuildOutputLocation%";
Configuration="Release";Platform="Any CPU";TargetFrameworkVersion=v4.6.1
copy /Y "%BuildOutputLocation%"\%ProjectDll% 
"%NugetLocation%"\lib\net461\%ProjectDll%

راز داخل switch /p

زمانی که به فایل .csproj نگاه می کنید، ما می بینیم که عناصر <propertyGroup> وجود دارد با بسیاری عنصر در داخل آن دقیقا در اینجا:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" 

xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$(MSBuildExtensionsPath)\
   $(MSBuildToolsVersion)\Microsoft.Common.props" 

   Condition="Exists('$(MSBuildExtensionsPath)\
   $(MSBuildToolsVersion)\Microsoft.Common.props')" />
   <PropertyGroup>
      <!--    €¦     -->
       <OutputType>Library</OutputType>
        <!--    €¦     -->
       <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
      <!--    €¦     -->
   </PropertyGroup>

هر عنصر زیر تگ <PropertyGroup> یک خاصیت است که می تواند تنظیم شود. (در ویژوال استایو Project setting است) بنابراین کامپایل کردن نسخه دیگر .NET به همین سادگی تغییر تگ <TargetFrameworkVersion> است.

اما پرچم /p کار را آسان تر می کند:

cd /d "%NugetLocation%"
%nuget% pack %ProjectNuspec%

آموزش سی شارپ