c# - tutorial - nuget package explorer
Garantiza la misma versiĆ³n de los paquetes nuget. (4)
Tenemos un marco que se divide en muchos proyectos separados en una solución. Ahora quiero crear paquetes NuGet para cada proyecto por separado, pero garantizo que solo se puede usar una versión del marco en una solución (posiblemente en varios proyectos).
Por ejemplo, digamos que el marco está compuesto por dos proyectos:
Framework
Framework_1
Framework_2
Ahora, al usar este marco, un proyecto puede hacer referencia a Framework_1
, mientras que otro proyecto hace referencia a Framework_2
. Quiero asegurarme de que ambos paquetes tengan la misma versión (puntos de bonificación si hay un proceso sencillo de un solo paso para actualizar a una versión más nueva)
Pensé que solo definiría un paquete de Framework de nivel de solución del cual todos los demás paquetes dependan estrictamente. El problema es que NuGet no tiene problemas simplemente instalando varias versiones del paquete de nivel de solución.
Básicamente probé lo siguiente:
Archivo nuspec a nivel de solución :
<?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>
Y un paquete nuspec por una parte:
<?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>
El problema ahora es si intenté instalar, diga otro paquete My.Framework.EF
con la versión 1.0.1
y una dependencia explícita de My.Framework
1.0.1 Visual Studio
simplemente instalaría My.Framework
dos veces, una vez con la versión 1.0.0 y una vez con 1.0.1.
Puede crear una prueba unitaria simple dentro de su solución para advertirle cuando tenga un problema. El código está abajo.
Deberá install-package NuGet.Core
dentro de su proyecto de prueba de unidad para que funcione el siguiente código.
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;
}
}
Resulta que puede llamar a Install-Package $package.Id -version <someVersion>
dentro de Install.ps1, lo que hará que la versión instalada originalmente se desinstale y que la versión especificada se instale.
Una versión ligeramente simplificada es la siguiente:
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
}
Yo arrancaría el "Paquete NuGet a nivel de solución", dividiría su marco en componentes y crearía un paquete NuGet por componente. Nadie va a tener un solo proyecto que haga referencia a su paquete NuGet "Framework Wrapper" y código para lógica de negocios, acceso a datos y WCF dentro de ese único proyecto.
Entonces, lo que debe hacer es aclarar cuál es realmente su lógica de dependencia y cuál es el razonamiento detrás de querer aplicar estrictamente una política de la misma versión .
Por ejemplo, digamos que My.Framework.BL tiene una dependencia en My.Framework.DAL. Entonces, en este punto, solo tiene 2 archivos Nuspec y 2 paquetes NuGet, con el .nuspec de su My.Framework.BL con el siguiente aspecto:
<dependencies>
<dependency id="My.Framework.DAL" version="1.0.0" />
</dependencies>
Y con su My.Framework.DAL que no contiene dependencias específicas de My.Framework.
Esto está bien, y su solución de querer juntar estrechamente el número asociado con la versión es problemática por varias razones. Lo primero y más importante es que confundirá a los consumidores de su marco si actualizó My.Framework.DAL cuando tiene 0 cambios, pero tuvo que actualizarlo porque cambió My.Framework.BL.
Podría pasar un mes, o más, posiblemente, y no tener que actualizar una dependencia de My.Framework, dependiendo del nivel de abstracción de su marco y del grado de programación de bajo nivel que esté realizando. En mi opinión, tener que actualizar las versiones dll de Core Framework cuando en realidad no hay cambios nuevos es un problema MUCHO mayor que los números de versión de todas las dll de My.Framework que son iguales. Aclamaciones. :)
Here están las referencias de documentos nuspec.
puede restringir la versión de su paquete usando la siguiente sintaxis en su packages.config como:
<package id="jQuery" version="1.9.1" allowedVersions="[1.9.1]" />
También de la documentación original de nuget: cuando crea un paquete NuGet, puede especificar dependencias para el paquete en el archivo .nuspec.
<dependency id="ExamplePackage" version="[1,3)" />
En el ejemplo, la versión 1 y la versión 2.9 serían aceptables, pero no 0.9 o 3.0.
Supongo que puede limitarlo de esta manera a un solo o cierto rango de versiones. Here puedes leer más sobre esto.