Bir meta pakete bağlı olarak bir netstandard kitaplığının uygulama etkileri nelerdir?


100

Netstandard1.3'ü hedeflemek ve aynı zamanda kullanmak istediğim bir sınıf kitaplığım olduğunu varsayalım BigInteger. İşte önemsiz bir örnek - tek kaynak dosya 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);            
    }
}

Dünyasına geri project.jsondöndüğümde netstandard1.3, frameworksbölümünde hedef System.Runtime.Numericsalırdım ve açık bir bağımlılığım olurdu , örneğin 4.0.1 sürümüne. Oluşturduğum nuget paketi sadece bu bağımlılığı listeleyecek.

Csproj tabanlı dotnet kalıp cesur yeni dünyada bir var (ben komut satırı araçları v1.0.1 kullanıyorum) örtük meta pakettir paket referans için NETStandard.Library 1.6.1hedeflerken netstandard1.3. Bu, proje dosyamın gerçekten küçük olduğu anlamına gelir, çünkü açık bağımlılığa ihtiyaç duymaz:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.3</TargetFramework>
  </PropertyGroup>
</Project>

... ancak üretilen nuget paketinin bir bağımlılığı var NETStandard.Library, bu da küçük kütüphanemi kullanmak için orada her şeye ihtiyacınız olduğunu gösteriyor.

Bu işlevi kullanarak devre dışı bırakabilirim ve DisableImplicitFrameworkReferencesardından bağımlılığı manuel olarak tekrar ekleyebilirim:

<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>

Şimdi NuGet paketim tam olarak neye bağlı olduğunu söylüyor. Sezgisel olarak, bu "daha zayıf" bir paket gibi geliyor.

Öyleyse kitaplığımın bir tüketicisi için tam olarak ne fark var? Birisi onu bir UWP uygulamasında kullanmaya çalışırsa, bağımlılıkların ikinci, "kırpılmış" biçimi, ortaya çıkan uygulamanın daha küçük olacağı anlamına mı gelir?

DisableImplicitFrameworkReferencesAçıkça belgelemeyerek (gördüğüm kadarıyla; bir konuda okudum ) ve bir proje oluştururken örtük bağımlılığı varsayılan hale getirerek, Microsoft kullanıcıları yalnızca meta pakete güvenmeye teşvik ediyor - ancak nasıl olabilirim Bir sınıf kitaplığı paketi oluştururken dezavantajları olmadığından emin misiniz?


3
Bağımlılık azaltmanın üzerinde çalışıldığına dikkat edilmelidir . Şu anda, Hello World!bağımsız bir uygulamanın boyutu <10MB'ye düşürülmüştür.
ABarney

@ABarney 10MB, klasik bir .NET Framework C # merhaba dünya projesinin < 20KB boyutuna kıyasla hala çok fazla .
Dai

Yanıtlar:


76

Geçmişte, geliştiricilere NETStandard.LibraryNuGet paketlerinden meta paketine ( ) başvurma, bunun yerine System.Runtimeve gibi tek tek paketlere başvurma önerisi verdik System.Collections. Mantık, meta paketini .NET platformunun gerçek atomik yapı taşları olan bir grup paket için bir kısaltma olarak düşünmemizdi. Varsayım şuydu: Bu atomik blokların yalnızca bazılarını destekleyen, ancak hepsini desteklemeyen başka bir .NET platformu oluşturabiliriz. Bu nedenle, ne kadar az paket referans verirseniz, o kadar taşınabilir olursunuz. Takımımızın büyük paket grafiklerle nasıl başa çıktığı konusunda da endişeler vardı.

İlerlerken, bunu basitleştireceğiz:

  1. .NET Standard, atomik bir yapı taşıdır . Başka bir deyişle, yeni platformların .NET Standard'ı alt kümesine almasına izin verilmez - bunların hepsini uygulamaları gerekir.

  2. .NET Standard dahil olmak üzere, platformlarımızı tanımlamak için paketleri kullanmaktan uzaklaşıyoruz .

Bu, artık .NET Standard için herhangi bir NuGet paketine başvurmanız gerekmeyeceği anlamına gelir. Bağımlılığınızı lib klasörüyle ifade ettiniz, bu, diğer tüm .NET platformları, özellikle de .NET Framework için tam olarak nasıl çalıştığıdır.

Ancak, şu anda aletlerimiz referans olarak yanmaya devam edecek NETStandard.Library. Bunda da bir zarar yok, sadece ileriye giderken gereksiz hale gelecektir.

Bu soruyu dahil etmek için .NET Standard deposundaki SSS'yi güncelleyeceğim .

Güncelleme : Bu soru artık SSS'nin bir parçası .


9
Teşekkürler - bu çok mantıklı. Sanırım kısmen kafam karışmıştı çünkü project.json dünyasında, paketler mantıksal olarak hedeflediğim çerçevenin parçası olduğunda bile bağımlılıklar eklemek zorunda kaldım (örn. Netstandard1.3 için System.Runtime.Numerics) - bu yüzden NETStandard.Library olduğunu düşündüm onları gerçekten bağımlılıklar olarak çekiyor.
Jon Skeet

2
Bummer. Paketlere atıfta bulunma fikrini beğendim, çünkü bütün "mutfak lavabosu" yerine sadece istediğim şeye referans verebileceğimi hissettim. Belki de bunu doğru düşünmüyorum?
Nate Barbettini

3
İlle de yanlış düşünmüyorsun, ama soru neden önemsediğin. Platformun sonsuz bir şekilde oluşturulamaz olduğunu anlamak önemlidir. Paylaşılan bir çerçeve ortamında (.NET Framework, Mono, .NET Core) çalıştırdığınızda, tüm bu bitler yine de mevcuttur. Kendi kendine yeten bir uygulama oluşturursanız (Xamarin, Mono /. Her iki durumda da, daha küçük bloklara referans vermeyerek hiçbir şey kaybetmiyorsunuz.
Immo Landwerth

3
Derleyicinin, bir geliştiricinin bir iş mantığı projesinde bu pakete izin vermeyerek bir http talebinde bulunmasını engellemek gibi kuralları zorlamasına ne dersiniz?
David Ferretti

Zorunlu değil, ama bunu nasıl uyguluyorsunuz, yani geliştiricinin referansı eklemesini engelleyen nedir? Katman kurallarını zorlamak ve derleme makinesinde hatalara neden olmak için derleme sırasında enjekte edilen bir analizci yazardım.
Immo Landwerth

19

Ekip, en ince paket setinin ne olduğunu bulmanızı tavsiye ederdi. Artık bunu yapmıyorlar ve insanların bunun yerine NETStandard.Library'yi getirmelerini öneriyorlar (SDK tarzı bir proje olması durumunda, bu sizin için otomatik olarak yapılacaktır).

Bunun neden olduğu konusunda hiçbir zaman tamamen açık bir cevap almadım, bu yüzden bazı eğitimli tahminler yapmama izin verin.

Birincil neden, muhtemelen hedef çerçeveleri değiştirirken kendinizi izlemeniz gerekecek bağımlı kitaplıkların sürümlerindeki farklılıkları gizlemelerine izin vermesidir. Ayrıca, SDK tabanlı proje dosyalarıyla çok daha kullanıcı dostu bir sistemdir, çünkü açıkçası platformun düzgün bir bölümünü elde etmek için herhangi bir referansa ihtiyacınız yoktur (aynen Desktop-land'daki varsayılan referanslarda, özellikle mscorlib'de alıştığınız gibi) ).

Bir netstandardkitaplık veya netcoreappuygulama olmanın ne anlama geldiğinin meta tanımını uygun NuGet paketine göndererek, Visual Studio (veya dotnet new) onları gördüğü gibi bu şeylerin tanımına herhangi bir özel bilgi eklemek zorunda kalmazlar .

Statik analiz, yayınlama sırasında gönderilen DLL'leri sınırlamak için kullanılabilir; bu, bugün UWP için yerel derleme yaparken yaptıkları bir şeydir (bazı uyarılarda da olsa). Bunu bugün .NET Core için yapmıyorlar, ancak bunun düşündükleri bir optimizasyon olduğunu düşünüyorum (yerel kodu desteklemenin yanı sıra).

Eğer seçerseniz, sizi çok seçici olmaktan alıkoyan hiçbir şey yoktur. Ben size neredeyse aynı zamanda (herkesin getiriyor farz olacak çünkü amacı yendi yapıyor sadece birini olduğunuzu göreceksiniz inanıyoruz NETStandard.Libraryya Microsoft.NETCore.App).


6
Katılıyorum, eğer herhangi biri gelirse, birden fazla bağımlılık olduğunda, kesinlikle amacı bozguna uğratır NETStandard.Library. Eğer ... biraz kendi kendini besleyen, elbette var ben bağlıdır NETStandard.LibraryNoda Zamanın üzerine inşa araçlar başka kütüphane Şimdi için seçici olmak cazip gelebilir Döşeme bağımlılıkları için bir neden, vb sahip olduğunu, Noda Kez (Noda Zamanı 2.0'a doğru ilerlerken) daha sonra konvansiyonlar oluşturulduktan sonra biraz gevşeyin - seçiciden lib tabanlıya geçişin kesintisiz bir değişiklik olacağını varsayıyorum, ancak bunun tersi doğru değil.
Jon Skeet

8

Örtülü referansı devre dışı bırakmanıza gerek yoktur. Kitaplığın üzerinde çalışabileceği tüm platformlar, NETStandard.Librarybağımlılığın gerektireceği derlemelere zaten sahip olacaktır.

.NET Standart Kitaplığı, .NET Core veya .NET Framework gibi bilinen bir platformlar ve platform sürümleri kümesinde var olması garanti edilen bir dizi API sağlayan, karşı derlediğiniz bir dizi başvuru derlemesidir. . Bu derlemelerin bir uygulaması değildir, yalnızca derleyicinin kodunuzu başarılı bir şekilde oluşturmasına izin verecek kadar API şekli yeterlidir.

Bu API'lerin uygulanması, .NET Core, Mono veya .NET Framework gibi bir hedef platform tarafından sağlanır. Platformun önemli bir parçası oldukları için platformla birlikte gönderilirler. Yani daha küçük bir bağımlılık kümesi belirtmenize gerek yok - her şey zaten var, bunu değiştirmeyeceksiniz.

NETStandard.LibraryPaket Bu referans derlemeleri içerir. Bir kafa karışıklığı noktası, sürüm numarasıdır - paket sürüm 1.6.1'dir, ancak bu ".NET Standard 1.6" anlamına gelmez. Bu sadece paketin sürümü.

Hedeflediğiniz .NET Standardının sürümü, projenizde belirttiğiniz hedef çerçeveden gelir.

Bir kitaplık oluşturuyorsanız ve .NET Standard 1.3'te çalışmasını istiyorsanız NETStandard.Library, şu anda sürüm 1.6.1'de bulunan pakete başvurursunuz. Ancak daha da önemlisi, proje dosyanız hedeflenir netstandard1.3.

NETStandard.LibraryPaket size hedef çerçeve takma bağlı referans meclislerinin farklı bir dizi vermek (ı kısalık için basitleştirerek ediyorum, ama düşünecek lib\netstandard1.0, lib\netstandard1.1ve bağımlılık grupları ). Yani projeniz hedefliyorsa netstandard1.3, 1.3 referans derlemelerini alacaksınız. Hedeflerseniz netstandard1.6, 1.6 referans derlemelerini alırsınız.

Bir uygulama oluşturuyorsanız, .NET Standard'ı hedefleyemezsiniz. Mantıklı değil - bir spesifikasyona göre koşamazsınız. Bunun yerine, net452veya gibi somut platformları hedeflersiniz netcoreapp1.1. NuGet, bu platformlar ve netstandardhedef çerçeve adları arasındaki eşlemeyi bilir, bu nedenle hangi lib\netstandardX.Xklasörlerin hedef platformunuzla uyumlu olduğunu bilir . Ayrıca, bağımlılıklarının NETStandard.Libraryhedef platform tarafından karşılandığını da bilir , bu nedenle başka montajları çekmez.

Benzer şekilde, bağımsız bir .NET Core uygulaması oluştururken, .NET Standard uygulama derlemeleri uygulamanızla kopyalanır. Referansı NETStandard.Librarybaşka herhangi bir yeni uygulamayı getirmez.

Not dotnet publishbağımsız bir uygulama yaratacak , ancak şu anda kırparak yapmaz olmayacak ve tüm meclisleri yayınlayacaktır. Bu, araçlarla otomatik olarak ele alınacaktır , bu nedenle, kitaplığınızdaki bağımlılıkların kırpılması burada yardımcı olmayacaktır.

Nerede hayal tek yer olabilir kaldırmak için yardımcı NETStandard.Library.NET Standard desteklemeyen bir platform hedefliyorsanız referanstır ve geçişli tüm bağımlılıklarını çalıştırmak nerede .NET Standard bir paket bulabilirsiniz hedef platformunuzda. Bu faturaya uyan çok fazla paket olmadığından şüpheleniyorum.


Bunu yaparsanız dotnet publishbelirli çalışma nedeniyle, dotnet.exe (veya Linux / OS X eşdeğeri) dahil tüm bağımlılıkları getirecektir. Bu, o noktada tamamen bağımsız bir dağıtım olmalıdır. Bir birim test projesi için sonuçlara göz atın: gist.github.com/bradwilson/6cc5a8fdfa18230aa6c99b851fb85c01
Brad Wilson

4
Sanırım son paragraf tam olarak mesele ... ve sorun olmasa, neden netstandard1.x'in farklı sürümlerine ihtiyacımız olsun ki? Her platformda her şey netstandard1.6'ya sahipse, neden konsept olarak netstandard1.0 bile var ? Benim için kafa karıştıran kısım bu.
Jon Skeet

1
Ve .NET Standard'ı destekleyen platformların listesi birçok Unity platformundan HERHANGİ BİRİNİ içermiyor.
citizenmatt

1
(Sabrınız çok takdir ediliyor, btw. Gerçekten bunların mantıklı olacağını ve birçok geliştiriciye yardımcı olacağını umuyorum ...)
Jon Skeet

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.