nuget - paquetes - ¿Cuáles son las implicaciones de aplicación de una biblioteca netstandard dependiendo de un metapaquete?
nuget pack (3)
El equipo solía recomendar averiguar cuál era el conjunto de paquetes más delgado. Ya no hacen esto, y recomiendan que las personas solo traigan NETStandard.Library en su lugar (en el caso de un proyecto de estilo SDK, esto se hará automáticamente por usted).
Nunca he recibido una respuesta totalmente directa de por qué fue así, así que permítanme hacer algunas conjeturas fundamentadas.
Es probable que la razón principal sea que les permite ocultar las diferencias en las versiones de las bibliotecas dependientes que, de lo contrario, tendrían que rastrearse a sí mismos al cambiar los marcos de destino. También es un sistema mucho más fácil de usar con los archivos de proyecto basados en SDK, porque francamente no necesita referencias para obtener una parte decente de la plataforma (al igual que solía hacerlo con las referencias predeterminadas en Desktop-land, especialmente mscorlib )
Al
netstandard
de lo que significa ser una biblioteca
netstandard
o una aplicación
netcoreapp
en el paquete NuGet apropiado, no tienen que desarrollar ningún conocimiento especial en la definición de esas cosas como Visual Studio (o
dotnet new
) los ve
El análisis estático podría usarse durante la publicación para limitar las DLL enviadas, que es algo que hacen hoy cuando compilan de forma nativa para UWP (aunque con algunas advertencias). No lo hacen hoy para .NET Core, pero supongo que es una optimización que han considerado (además de admitir código nativo).
No hay nada que te impida ser muy selectivo, si así lo eliges.
Creo que descubrirá que es casi el único que lo hace, lo que también frustra el propósito (ya que se supondrá que todo el mundo trae
NETStandard.Library
o
Microsoft.NETCore.App
).
Supongamos que tengo una biblioteca de clases a la que quiero apuntar netstandard1.3, pero también uso
BigInteger
.
Aquí hay un ejemplo trivial: el único archivo fuente es
Adder.cs
:
using System;
using System.Numerics;
namespace Calculator
{
public class Adder
{
public static BigInteger Add(int x, int y)
=> new BigInteger(x) + new BigInteger(y);
}
}
De vuelta en el mundo de
project.json
, apuntaría a
netstandard1.3
en la sección de
frameworks
y tendría una dependencia explícita en
System.Runtime.Numerics
, por ejemplo, la versión 4.0.1.
El paquete nuget que creo enumerará solo esa dependencia.
En el valiente y nuevo mundo de las herramientas de dotnet basadas en csproj (estoy usando v1.0.1 de las herramientas de línea de comandos) hay una
referencia implícita de paquete
de
NETStandard.Library 1.6.1
a
NETStandard.Library 1.6.1
cuando apunta a
netstandard1.3
.
Esto significa que mi archivo de proyecto es realmente pequeño, porque no necesita la dependencia explícita:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
</Project>
... pero el paquete nuget producido depende de
NETStandard.Library
, lo que sugiere que para usar mi pequeña biblioteca, necesita
todo lo
que necesita.
Resulta que puedo deshabilitar esa funcionalidad usando
DisableImplicitFrameworkReferences
, y luego agregar la dependencia manualmente nuevamente:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Numerics" Version="4.0.1" />
</ItemGroup>
</Project>
Ahora mi paquete NuGet dice exactamente de qué depende. Intuitivamente, esto se siente como un paquete "más delgado".
Entonces, ¿cuál es la diferencia exacta para un consumidor de mi biblioteca? Si alguien intenta usarlo en una aplicación para UWP, ¿la segunda forma de dependencias "recortadas" significa que la aplicación resultante será más pequeña?
Al no documentar
DisableImplicitFrameworkReferences
claramente (por lo que he visto; lo leí
en un problema
) y al hacer que la dependencia implícita sea la predeterminada al crear un proyecto, Microsoft está
alentando a los
usuarios a que solo dependan del metapaquete, pero ¿cómo puedo hacerlo? asegúrese de que no tenga inconvenientes cuando produzca un paquete de biblioteca de clases?
En el pasado, les hemos dado a los desarrolladores la recomendación de no hacer referencia al
NETStandard.Library
(
NETStandard.Library
) de los paquetes NuGet, sino a paquetes individuales, como
System.Runtime
y
System.Collections
.
La razón era que pensábamos en el metapaquete como una abreviatura de un conjunto de paquetes que eran los bloques de construcción atómicos reales de la plataforma .NET.
La suposición era: podríamos terminar creando otra plataforma .NET que solo sea compatible con algunos de estos bloques atómicos, pero no con todos.
Por lo tanto, cuantos menos paquetes haga referencia, más portátil será.
También hubo preocupaciones con respecto a cómo nuestras herramientas se ocupan de los grandes gráficos de paquetes.
En el futuro, simplificaremos esto:
-
.NET Standard es un bloque de construcción atómico . En otras palabras, a las nuevas plataformas no se les permite subconjuntar .NET Standard, tienen que implementarlo todo.
-
Nos estamos alejando del uso de paquetes para describir nuestras plataformas , incluido .NET Standard.
Esto significa que ya no tendrá que hacer referencia a ningún paquete NuGet para .NET Standard. Expresó su dependencia con la carpeta lib, que es exactamente cómo ha funcionado para todas las demás plataformas .NET, en particular .NET Framework.
Sin embargo, en este momento nuestras herramientas aún se
NETStandard.Library
en la referencia a
NETStandard.Library
.
No hay daño en eso tampoco, simplemente se volverá redundante en el futuro.
Actualizaré las FAQ en el repositorio de .NET Standard para incluir esta pregunta.
Actualización : esta pregunta ahora forma parte de las preguntas frecuentes .
No debería necesitar deshabilitar la referencia implícita.
Todas las plataformas en las que la biblioteca podrá ejecutarse ya tendrán los ensamblados que
NETStandard.Library
dependencia
NETStandard.Library
.
.NET Standard Library es una especificación, un conjunto de ensamblados de referencia con los que compila que proporciona un conjunto de API que se garantiza que existen en un conjunto conocido de plataformas y versiones de plataformas, como .NET Core o .NET Framework . No es una implementación de estos ensamblados, solo la forma de API suficiente para permitir que el compilador construya con éxito su código.
La implementación de estas API es proporcionada por una plataforma de destino, como .NET Core, Mono o .NET Framework. Se envían con la plataforma, porque son una parte esencial de la plataforma. Por lo tanto, no es necesario especificar un conjunto de dependencias más pequeño: todo ya está allí, no lo cambiará.
El paquete
NETStandard.Library
proporciona estos ensamblados de referencia.
Un punto de confusión es el número de versión: el paquete es la versión 1.6.1, pero esto no significa ".NET Standard 1.6".
Es solo la versión del paquete.
La versión del estándar .NET al que se dirige proviene del marco de destino que especifique en su proyecto.
Si está creando una biblioteca y desea que se ejecute en .NET Standard 1.3, debe hacer referencia al paquete
NETStandard.Library
, actualmente en la versión 1.6.1.
Pero lo más importante, su archivo de proyecto apuntaría a
netstandard1.3
.
El paquete
NETStandard.Library
le dará un conjunto diferente de ensambles de referencia dependiendo de su nombre de marco de referencia (estoy simplificando por brevedad, pero piense en
lib/netstandard1.0
,
lib/netstandard1.1
y
grupos de dependencia
).
Entonces, si su proyecto apunta a
netstandard1.3
, obtendrá los ensamblajes de referencia 1.3.
Si apunta a
netstandard1.6
, obtendrá los ensamblajes de referencia 1.6.
Si está creando una aplicación, no puede apuntar al estándar .NET.
No tiene sentido: no puede ejecutar una especificación.
En su lugar, apunta a plataformas concretas, como
net452
o
netcoreapp1.1
.
NuGet conoce el mapeo entre estas plataformas y los
netstandard
framework de destino netstandard, así que sabe qué carpetas
lib/netstandardX.X
son compatibles con su plataforma de destino.
También sabe que las dependencias de
NETStandard.Library
son satisfechas por la plataforma de destino, por lo que no atraerá ningún otro ensamblado.
Del mismo modo, al crear una aplicación .NET Core independiente, los ensamblados de implementación de .NET Standard se copian con su aplicación.
La referencia a
NETStandard.Library
no
NETStandard.Library
ninguna otra aplicación nueva.
Tenga en cuenta que
dotnet publish
creará una aplicación independiente , pero actualmente no lo hará, y publicará todos los ensamblajes. Esto se manejará automáticamente con herramientas , por lo que nuevamente, el recorte de dependencias en su biblioteca no ayudará aquí.
El único lugar que puedo imaginar donde
podría
ayudar a eliminar el
NETStandard.Library
referencia es si está apuntando a una plataforma que no es compatible con el estándar .NET, y puede encontrar un paquete desde el estándar .NET donde todos los transitivos las dependencias pueden ejecutarse en su plataforma de destino.
Sospecho que no hay muchos paquetes que se ajusten a esa factura.