簡體   English   中英

保證相同版本的nuget包

[英]Guarantee same version of nuget packages

我們有一個框架,在一個解決方案中分成許多單獨的項目。 我現在想為每個單獨的項目創建NuGet包, 保證只能在一個解決方案中使用一個版本的框架(可能跨多個項目)。

例如,假設框架由兩個項目組成:

Framework
   Framework_1
   Framework_2

現在,當使用此框架時,一個項目可能引用Framework_1 ,而另一個項目引用Framework_2 我想確保兩個軟件包具有相同的版本(如果有一個簡單的單步過程升級到新版本,則可獲得獎勵積分)

我想我會定義一個解決方案級別的Framework包,所有其他包都嚴格依賴它。 問題是NuGet只需安裝多個版本的解決方案級別包就沒有問題。

基本上我嘗試了以下內容:

解決方案級別的nuspec文件:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>My.Framework</id>
    <version>1.0.0</version>
    <title>My.Framework</title>
    <authors>voo</authors>
    <owners>voo</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Some Framework Solution Package</description>
    <copyright>Copyright ©  2015</copyright>
  </metadata>
</package>

一個部分的nuspec包:

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>My.Framework.BL</id>
    <version>1.0.0</version>
    <title>My.Framework.BL</title>
    <authors>voo</authors>
    <owners>voo</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Business Layer</description>
    <copyright>Copyright ©  2015</copyright>
    <dependencies> 
        <dependency id="My.Framework" version="[1.0.0]"/>
    </dependencies>
  </metadata>
</package>

現在的問題是,如果我嘗試安裝,說另一個版本1.0.1 My.Framework.EF包和My.Framework 1.0.1的顯式依賴, Visual Studio只會安裝My.Framework兩次 - 一次使用版本1.0.0和一次1.0.1。

您可以通過在packages.config中使用以下語法來約束包的版本,如:

<package id="jQuery" version="1.9.1" allowedVersions="[1.9.1]" />

同樣來自原始nuget文檔:創建NuGet包時,可以在.nuspec文件中指定包的依賴關系。

<dependency id="ExamplePackage" version="[1,3)" />

在示例中,版本1和版本2.9是可接受的,但不是0.9或3.0。

我認為您可以通過這種方式將其限制為單個或特定范圍的版本。 在這里,您可以閱讀更多相關信息。

您可以在解決方案中創建一個簡單的單元測試,以便在出現問題時向您發出警告。 代碼如下。

您需要在單元測試項目中install-package NuGet.Core才能使下面的代碼正常工作。

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NuGet;

[TestClass]
public class NugetPackagesTest
{
    /// <summary>
    /// This test method makes sure that we do not install different versions of the same nuget package
    /// across the solution. For example this test will fail if one project references EntityFramework
    /// version 6.1.3 and another project references version 6.2.0. Having different versions of the same
    /// package installed often results in unexpected and hard-to-understand errors.
    /// </summary>
    [TestMethod]
    public void PackagesAccrossProjectsAreOfSameVersion()
    {
        var dir = GetSolutionRoot();

        Debug.Assert(dir != null, nameof(dir) + " != null");

        var filePaths = Directory.GetFiles(dir.FullName, "*packages.config", SearchOption.AllDirectories);
        var installedPackages = filePaths
            .Select(t => new PackageReferenceFile(t))
            .SelectMany(t => t.GetPackageReferences().Select(x => new { File = t, Package = x }))
            .GroupBy(t => t.Package.Id)
            .ToList();

        foreach (var package in installedPackages)
        {
            var versions = package
                .Select(t => t.Package.Version.ToNormalizedString())
                .Distinct()
                .ToList();

            var report = package
                .Select(t => $"{t.Package.Version} @ {t.File.FullPath}")
                .OrderBy(t => t);

            Assert.IsTrue(
                versions.Count == 1,
                $"Multiple versions of package {package.Key} are installed: {string.Join(", ", versions)}.\n" +
                $"{string.Join("\n", report)}");
        }
    }

    private static DirectoryInfo GetSolutionRoot()
    {
        var current = AppDomain.CurrentDomain.BaseDirectory;
        var dir = Directory.GetParent(current);

        while (dir != null)
        {
            // TODO: replace with name your solution's folder.
            if (dir.Name == "MySolution")
            {
                dir = dir.Parent;
                break;
            }

            dir = dir.Parent;
        }

        return dir;
    }
}

我會刪除“解決方案級NuGet包”,並將您的框架划分為組件,並為每個組件創建一個NuGet包。 沒有人會有一個單獨的項目引用你的“Framework Wrapper”NuGet包,以及單個項目中的業務邏輯,數據訪問和WCF的代碼。

那么你需要做的是,弄清楚你的依賴邏輯究竟是什么,以及想要嚴格執行同一版本策略背后的原因是什么。

例如,假設My.Framework.BL依賴於My.Framework.DAL。 所以此時你只有2個Nuspec文件和2個NuGet包,你的My.Framework.BL的.nuspec看起來像這樣:

<dependencies>
  <dependency id="My.Framework.DAL" version="1.0.0" />
</dependencies>

並且您的My.Framework.DAL不包含My.Framework特定的依賴項。

這很好,並且由於某些原因,您希望緊密耦合與版本相關聯的數字的解決方案存在問題。 第一個也是最重要的是,如果你在更改了0時更新了My.Framework.DAL,它會讓你的框架消費者感到困惑,但你必須更新它,因為你改變了My.Framework.BL。

您可能需要一個月或更長時間,而不必更新My.Framework依賴項,具體取決於框架的抽象級別,以及您正在執行的低級編程程度。 在我看來,當沒有實際任何新的更改時,必須更新Core Framework DLL版本是一個比所有My.Framework dll版本號相同的問題。 干杯。 :)

以下是nuspec參考文檔。

事實證明,您可以 Install.ps1中調用Install-Package $package.Id -version <someVersion> 這將導致卸載最初安裝的版本並安裝指定的版本。

稍微簡化的版本如下:

param($installPath, $toolsPath, $package, $project)

function GetInstallingVersion() {
    $package.Version
}

# Gets the current version of the used framework. 
# If no framework is yet installed, we set the framework version 
# to the one that's being installed right now.
function GetCurrentFrameworkVersion() {
    $solutionPath = Split-Path $dte.Solution.FileName
    $fwkVersionFile = "${solutionPath}\framework_version.txt"
    if (Test-Path $fwkVersionFile) {
        return Get-Content $fwkVersionFile
    } 
    else {
        $installingVersion = GetInstallingVersion
        $installingVersion > $fwkVersionFile
        return $installingVersion
    }
}

$currentFwkVersion = GetCurrentFrameworkVersion
$installingVersion = GetInstallingVersion

if ($currentFwkVersion -ne $installingVersion) {
    Install-Package $package.Id -version $currentFwkVersion
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM