¿Cuáles son las implicaciones de aplicación de una biblioteca netstandard dependiendo de un metapaquete?


Supongamos que tengo una biblioteca de clases a la que quiero apuntar netstandard1.3, pero también usar BigInteger. Este es 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, me dirigiría a netstandard1.3 en la sección frameworks, y tendría una dependencia explícita de System.Runtime.Numerics, por ejemplo, la versión 4.0.1. El paquete nuget que creo enumerará solo esa dependencia.

En el nuevo mundo de herramientas dotnet basadas en csproj (estoy usando v1. 0. 1 de las herramientas de línea de comandos) hay una referencia implícita del paquete metapaquete a NETStandard.Library 1.6.1 cuando se dirige a netstandard1.3. Esto significa que mi archivo de proyecto es muy 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 tiene una dependencia de NETStandard.Library, lo que sugiere que para usar mi pequeña biblioteca, necesita todo allí.

Resulta que puedo desactivar esa funcionalidad usando DisableImplicitFrameworkReferences, luego agregar la dependencia manualmente de nuevo:

<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 El 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 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; leí sobre ello en un problema ) y al hacer que la dependencia implícita sea la predeterminada al crear una project, Microsoft están animando a los usuarios a depender solo del metapaquete, pero ¿cómo puedo estar seguro de que no tiene desventajas cuando estoy produciendo un paquete de biblioteca de clases?

Author: Athari, 2017-03-22

3 answers

En el pasado, hemos dado a los desarrolladores la recomendación de no hacer referencia al meta paquete (NETStandard.Library) de paquetes NuGet pero en su lugar referencia paquetes individuales, como System.Runtime y System.Collections. El la razón fue que pensamos en el paquete meta como una abreviatura de un montón de paquetes que eran los bloques de construcción atómicos reales de la plataforma. NET. El suposición era: podríamos terminar creando otra plataforma. NET que solo soporta algunos de estos bloques atómicos pero no todos. Por lo tanto, el menos paquetes de referencia, más portátil sería. También hubo preocupaciones con respecto a cómo nuestras herramientas se ocupan de los gráficos de paquetes grandes.

En el futuro, simplificaremos esto:

  1. . NET Standard es un bloque de construcción atómico . En otras palabras, nuevas plataformas no se les permite subconjunto. NET Estándar have tienen que implementar todo.

  2. Nos estamos alejando del uso de paquetes para describir nuestras plataformas, incluyendo. NET Estándar.

Esto significa que no tendrá que hacer referencia a ningún paquete NuGet para. NET Standard nunca más. 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 todavía se quemarán en la referencia a NETStandard.Library. No hay daño en eso tampoco, simplemente se convertirá redundante en el futuro.

Actualizaré el FAQ en el repositorio Estándar. NET para incluir esta pregunta.

Actualización : Esta pregunta es ahora parte de la FAQ.

 70
Author: Immo Landwerth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-25 00:31:10

El equipo solía recomendar averiguar cuál era el conjunto de paquetes más delgado. Ya no hacen esto, y recomiendan a la gente solo traer NETStandard.Biblioteca en su lugar (en el caso de un proyecto de estilo SDK, esto se hará automáticamente para usted).

Nunca he recibido una respuesta totalmente directa en cuanto a por qué fue eso, así que permíteme hacer algunas conjeturas educadas.

La razón principal es probable que sea que les permite ocultar las diferencias en las versiones de los dependientes bibliotecas que, de otro modo, tendría que realizar un seguimiento cuando cambie los marcos de trabajo 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 ninguna referencia para obtener una parte decente de la plataforma (al igual que solía hacer con las referencias predeterminadas en Desktop-land, especialmente mscorlib).

Empujando la meta-definición de lo que significa ser una biblioteca netstandard, o una aplicación netcoreapp en el paquete NuGet apropiado, ellos no tiene que construir ningún conocimiento especial en la definición de esas cosas como Visual Studio (o dotnet new) las ve.

El análisis estático se podría utilizar durante la publicación para limitar las DLL enviadas, que es algo que hacen hoy en día cuando se hace la compilación 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 desea. Creo que encontrarás que eres casi el único que lo hace, lo que también frustra el propósito (ya que se asumirá que todo el mundo está trayendo NETStandard.Library o Microsoft.NETCore.App).

 17
Author: Brad Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-22 11:28:14

No es necesario desactivar la referencia implícita. Todas las plataformas en las que la biblioteca podrá ejecutarse ya tendrán los ensamblados que requeriría la dependencia NETStandard.Library.

La Biblioteca Estándar de.NET es una especificación, un conjunto de ensamblados de referencia con los que se 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 lo suficiente de la forma de la API para permitir que el compilador construya su código con éxito.

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. Así que no hay necesidad de especificar un conjunto de dependencias más pequeño - todo ya está ahí, no cambiarás eso.

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 sólo la versión del paquete.

La versión del estándar.NET a la que te diriges proviene del marco de trabajo de destino que especifiques en tu proyecto.

Si está creando una biblioteca y desea que se ejecute en.NET Standard 1.3, debería hacer referencia al paquete NETStandard.Library, actualmente en la versión 1.6.1. Pero lo más importante, su archivo de proyecto se dirigiría netstandard1.3.

El paquete NETStandard.Library le dará un conjunto diferente de ensamblados de referencia dependiendo de su apodo de marco de destino (estoy simplificando por brevedad, pero creo lib\netstandard1.0, lib\netstandard1.1 y grupos de dependencias). Así que si su proyecto se dirige netstandard1.3, obtendrá los ensamblados de referencia 1.3. Si apunta netstandard1.6, obtendrá los ensamblados de referencia 1.6.

Si está creando una aplicación, no puede dirigirse al estándar.NET. No tiene sentido-no se puede ejecutar en un especificación. En su lugar, se dirige a plataformas de concreto, como net452 o netcoreapp1.1. NuGet conoce la asignación entre estas plataformas y los netstandard monikers del framework de destino, por lo que sabe qué carpetas lib\netstandardX.X son compatibles con su plataforma de destino. También sabe que las dependencias de NETStandard.Library están satisfechas por la plataforma de destino, por lo que no extraerá ningún otro ensamblado.

Del mismo modo, al crear una aplicación. NET Core independiente, los ensamblados de implementación estándar de. NET se copian con su app. La referencia a NETStandard.Library no trae ninguna otra aplicación nueva.

Tenga en cuenta que dotnet publish creará una aplicación independiente, pero no lo hará actualmente no hace recorte, y publicará todos los ensamblados. Esto será manejado automáticamente por herramientas, por lo que de nuevo, recortar dependencias en su biblioteca no ayudará aquí.

El único lugar que puedo imaginar donde podría ayudar a eliminar la referencia NETStandard.Library es si está apuntando a un plataforma que no admite el estándar. NET, y puede encontrar un paquete del Estándar. NET donde todas las dependencias transitivas pueden ejecutarse en su plataforma de destino. Sospecho que no hay muchos paquetes que se ajusten a esa factura.

 6
Author: citizenmatt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:33