메타 패키지에 따른 netstandard 라이브러리의 응용 프로그램 의미는 무엇입니까?


100

netstandard1.3을 대상으로하는 클래스 라이브러리가 있지만 BigInteger. 다음은 간단한 예입니다 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);            
    }
}

의 세계로 돌아 가면 섹션 에서 project.json대상 netstandard1.3을 지정하고 버전 4.0.1 frameworks에 대한 명시적인 종속성이 System.Runtime.Numerics있습니다. 내가 만든 너겟 패키지는 해당 종속성 만 나열합니다.

csproj 기반 DOTNET 공구의 용감한 새로운 세계에있다 (I 명령 줄 도구 1.0.1을 사용하고 있습니다) 암시 적 메타 패키지 패키지 참조NETStandard.Library 1.6.1대상으로하는 경우는 netstandard1.3. 이것은 명시적인 종속성이 필요하지 않기 때문에 내 프로젝트 파일이 정말 작다는 것을 의미합니다.

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

...하지만 생성 된 너겟 패키지는에 종속되어 있습니다 NETStandard.Library. 이는 내 작은 라이브러리를 사용하려면 거기에 모든 것이 필요함을 나타 냅니다.

을 사용하여 해당 기능을 비활성화 DisableImplicitFrameworkReferences한 다음 수동으로 종속성을 다시 추가 할 수 있습니다 .

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

이제 내 NuGet 패키지가 정확히 무엇에 의존하는지 알려줍니다. 직관적으로 이것은 "간단한"패키지처럼 느껴집니다.

그렇다면 내 도서관 소비자의 정확한 차이점은 무엇입니까? 누군가 UWP 응용 프로그램에서이를 사용하려고하면 두 번째 "잘린"형태의 종속성이 결과 응용 프로그램이 더 작아진다는 의미입니까?

DisableImplicitFrameworkReferences명확하게 문서화하지 않고 (내가 본 적이 있는 한 문제에서 읽었습니다 ) 프로젝트를 만들 때 암시 적 종속성을 기본값으로 설정함으로써 Microsoft는 사용자가 메타 패키지에만 의존 하도록 권장하고 있습니다. 클래스 라이브러리 패키지를 만들 때 단점이 없는지 확인하십시오.


3
의존성 조정이 작업 중이라는 점에 유의해야합니다 . 현재 Hello World!자체 포함 된 애플리케이션 의 크기는 10MB 미만으로 줄어 듭니다.
ABarney

@ABarney 10MB는 클래식 .NET Framework C # hello-world 프로젝트의 20KB 미만 크기에 비해 여전히 너무 많습니다 .
Dai

답변:


76

과거에는 NETStandard.LibraryNuGet 패키지에서 메타 패키지 ( )를 참조하지 않고 대신 System.Runtime및 같은 개별 패키지를 참조 하도록 개발자에게 권장했습니다 System.Collections. 그 이유는 메타 패키지를 .NET 플랫폼의 실제 원자 구성 요소 인 패키지 묶음의 약자로 생각했기 때문입니다. 가정은 다음과 같습니다. 우리는 이러한 원자 블록 중 일부만 지원하지만 전부는 지원하지 않는 또 다른 .NET 플랫폼을 만들 수 있습니다. 따라서 참조하는 패키지가 적을수록 휴대 성이 높아집니다. 툴링이 대형 패키지 그래프를 어떻게 처리하는지에 대한 우려도있었습니다.

앞으로 우리는 이것을 단순화 할 것입니다.

  1. .NET Standard는 원자 빌딩 블록 입니다. 즉, 새로운 플랫폼은 .NET Standard의 하위 집합이 허용되지 않으며 모든 것을 구현해야합니다.

  2. .NET Standard를 포함하여 플랫폼을 설명하기 위해 패키지를 사용하지 않습니다 .

즉, 더 이상 .NET Standard 용 NuGet 패키지를 참조 할 필요가 없습니다. 다른 모든 .NET 플랫폼, 특히 .NET Framework에서 정확히 작동하는 방식 인 lib 폴더로 종속성을 표현했습니다.

그러나 현재 우리의 툴링은 여전히 NETStandard.Library. 그것도 해가 없습니다. 앞으로 나아갈 때 중복 될 것입니다.

이 질문을 포함하도록 .NET Standard 리포지토리 의 FAQ 를 업데이트 하겠습니다.

업데이트 :이 질문은 이제 FAQ의 일부입니다 .


9
감사합니다-이것은 많은 의미가 있습니다. project.json 세계에서 패키지가 논리적으로 내가 대상으로하는 프레임 워크의 일부인 경우에도 종속성을 추가해야했기 때문에 부분적으로 혼란 스러웠습니다 (예 : netstandard1.3의 경우 System.Runtime.Numerics)-그래서 NETStandard.Library가 정말 의존성으로 끌어들입니다.
Jon Skeet

2
Bummer. 패키지를 참조한다는 아이디어가 마음에 들었습니다. 전체 "주방 싱크대"대신 내가 원하는 것만 참조 할 수있는 것 같았 기 때문입니다. 아마도 내가 그것에 대해 올바르게 생각하고 있지 않을까요?
Nate Barbettini

3
반드시 잘못된 방식으로 생각하는 것은 아니지만 문제는 당신이 관심을 갖는 이유입니다. 플랫폼이 무한하게 구성 될 수 없다는 것을 이해하는 것이 중요합니다. 공유 프레임 워크 환경 (.NET Framework, Mono, .NET Core)에서 실행하면 이러한 모든 비트가 어쨌든 존재합니다. 자체 포함 된 앱 (Xamarin, 링커 포함 Mono / .NET Core)을 빌드하는 경우 실제 사용량에 따라 자동으로 트리밍 할 수 있습니다. 따라서 어느 쪽이든 더 작은 블록을 참조하지 않아도 잃는 것은 없습니다.
Immo Landwerth

3
컴파일러가 해당 패키지를 허용하지 않음으로써 개발자가 비즈니스 로직 프로젝트에서 http 요청을하지 못하도록하는 것과 같은 규칙을 적용하게하는 것은 어떨까요?
데이비드 페레

반드시 그런 것은 아니지만 어떻게 적용합니까? 즉, 개발자가 참조를 추가하지 못하게하는 것은 무엇입니까? 빌드시 삽입되는 분석기를 작성하여 레이어 규칙을 적용하고 빌드 머신에서 오류를 발생시킵니다.
Immo Landwerth

19

팀은 가장 얇은 패키지 세트가 무엇인지 알아내는 것을 권장했습니다. 그들은 더 이상이 작업을 수행하지 않으며 대신 NETStandard.Library를 가져 오는 것이 좋습니다 (SDK 스타일 프로젝트의 경우이 작업이 자동으로 수행됨).

그 이유에 대해 완전히 솔직한 답을 얻지 못했기 때문에 몇 가지 정보를 바탕으로 추측 해 보도록하겠습니다.

주된 이유는 대상 프레임 워크를 변경할 때 자신을 추적해야하는 종속 라이브러리 버전의 차이를 숨길 수 있기 때문입니다. 또한 SDK 기반 프로젝트 파일을 사용하는 훨씬 더 사용자 친화적 인 시스템입니다. 솔직히 플랫폼의 적절한 청크를 얻기 위해 참조가 필요하지 않기 때문입니다. ).

netstandard라이브러리 또는 netcoreapp애플리케이션 이라는 것이 의미하는 메타 정의를 적절한 NuGet 패키지로 푸시하면 Visual Studio (또는 dotnet new)에서 볼 때 해당 항목의 정의에 특별한 지식을 구축 할 필요가 없습니다 .

게시 중에 정적 분석을 사용하여 제공된 DLL을 제한 할 수 있습니다. 이는 현재 UWP에 대한 네이티브 컴파일을 수행 할 때 수행하는 작업입니다 (일부주의 사항이 있음). 그들은 오늘날 .NET Core에 대해 그렇게하지 않지만 그들이 고려한 최적화라고 생각합니다 (네이티브 코드 지원).

당신이 그렇게 선택한다면, 당신이 매우 선택적이되는 것을 막을 수는 없습니다. 난 당신이 거의 또한 (이 모두가 초래되어 가정 할 것이기 때문에 목적 패배를하고있는 단 하나의, 걸 찾을 수 있습니다 생각 NETStandard.Library또는 Microsoft.NETCore.App).


6
둘 이상의 종속성이 있으면 그 중 하나가 NETStandard.Library. 물론 다소 자기 충족 적입니다 ... 제가NETStandard.Library Noda Time 에 의존 한다면 , Noda Time 위에 구축 된 다른 라이브러리는 의존성을 다듬을 이유가 없다는 것을 의미합니다. 지금은 선택적인 것이 좋습니다 (Noda Time은 2.0으로 향하는 것) 그런 다음 규칙이 확립되면 잠시 휴식을 취하십시오. 선택적에서 lib 기반으로 변경하는 것은 깨지지 않는 변경이 될 것이라고 가정하지만 그 반대는 사실이 아닙니다.
Jon Skeet

8

암시 적 참조를 비활성화 할 필요가 없습니다. 라이브러리를 실행할 수있는 모든 플랫폼에는 NETStandard.Library종속성에 필요한 어셈블리가 이미 있습니다 .

.NET 표준 라이브러리는 .NET Core 또는 .NET Framework와 같은 알려진 플랫폼 및 플랫폼 버전에 존재하도록 보장되는 API 집합을 제공하는 컴파일하는 참조 어셈블리 집합 인 사양입니다. . 이는 이러한 어셈블리의 구현이 아니며 컴파일러가 코드를 성공적으로 빌드 할 수 있도록 API 모양으로 충분합니다.

이러한 API에 대한 구현은 .NET Core, Mono 또는 .NET Framework와 같은 대상 플랫폼에서 제공됩니다. 플랫폼의 필수 부분이기 때문에 플랫폼과 함께 제공됩니다. 따라서 더 작은 종속성 세트를 지정할 필요가 없습니다. 모든 것이 이미 존재하므로 변경하지 않아도됩니다.

NETStandard.Library패키지는 이러한 기준 조립체를 제공한다. 혼란스러운 점은 버전 번호입니다. 패키지는 버전 1.6.1이지만 ".NET Standard 1.6"을 의미하지는 않습니다. 패키지의 버전 일뿐입니다.

대상으로하는 .NET Standard의 버전은 프로젝트에서 지정한 대상 프레임 워크에서 가져옵니다.

라이브러리를 만들고 .NET Standard 1.3에서 실행하려면 NETStandard.Library현재 버전 1.6.1에 있는 패키지를 참조합니다 . 하지만 더 중요한 것은 프로젝트 파일이netstandard1.3 .

NETStandard.Library패키지는 당신에게 당신의 대상 프레임 워크 모니 커에 따라 참조 어셈블리의 다른 세트 제공 (나는 간결 간단 해요,하지만 생각하는 것 lib\netstandard1.0, lib\netstandard1.1그리고 의존성 그룹 ). 따라서 프로젝트가을 대상으로 netstandard1.3하는 경우 1.3 참조 어셈블리를 얻을 수 있습니다. 를 대상으로하는 경우 netstandard1.61.6 참조 어셈블리를 얻을 수 있습니다.

응용 프로그램을 만드는 경우 .NET Standard를 대상으로 할 수 없습니다. 말이 안 돼요-당신은 사양에서 실행할 수 없습니다. 대신, 같은 콘크리트 플랫폼, 대상 net452또는 netcoreapp1.1. NuGet은 이러한 플랫폼과 netstandard대상 프레임 워크 모니 커 간의 매핑을 알고 있으므로 lib\netstandardX.X대상 플랫폼과 호환 되는 폴더를 알고 있습니다. 또한NETStandard.Library 대상 플랫폼에 의해 충족 있으므로 다른 어셈블리를 가져 오지 않습니다.

마찬가지로 독립 실행 형 .NET Core 앱을 만들 때 .NET Standard 구현 어셈블리가 앱과 함께 복사됩니다. 에 대한 참조 NETStandard.Library는 다른 새 앱을 가져 오지 않습니다.

참고 dotnet publish독립 실행 형 응용 프로그램을 만들 것입니다 ,하지만 현재 트리밍을하지 않습니다하지 않으며, 모든 어셈블리를 게시합니다. 이것은 tooling의해 자동으로 처리 되므로 라이브러리의 종속성을 다듬는 것은 여기서 도움이되지 않습니다.

참조 를 제거하는 것이 도움이 수있는 유일한 곳 NETStandard.Library은 .NET Standard를 지원하지 않는 플랫폼을 대상으로하고 모든 전이 종속성이 실행될 수있는 .NET Standard에서 패키지를 찾을 수있는 경우입니다. 타겟 플랫폼에서. 그 청구서에 맞는 패키지가 많지 않은 것 같습니다.


dotnet publish특정 런타임에 수행 하면 dotnet.exe (또는 이에 상응하는 Linux / OS X)를 포함한 모든 종속성을 가져옵니다. 이 시점에서 완전히 독립된 배포 여야합니다. 단위 테스트 프로젝트의 결과를 체크 아웃 : gist.github.com/bradwilson/6cc5a8fdfa18230aa6c99b851fb85c01
브래드 윌슨

4
마지막 단락이 정확히 문제라고 생각합니다. 문제가 아니라면 왜 다른 버전의 netstandard1.x가 필요합니까? 모든 플랫폼이 netstandard1.6의 모든이있는 경우, 그 이유도 개념으로 netstandard1.0를? 그것은 저에게 혼란스러운 부분입니다.
Jon Skeet

1
그리고 .NET Standard를 지원하는 플랫폼 목록에는 많은 Unity 플랫폼이 포함되어 있지 않습니다.
citizenmatt

1
(당신의 인내가 많이 BTW, 감사합니다 정말이 모든 메이크업 감각을 바라고, 그리고 많은, 많은 개발자들에게 도움이 될 것입니다 ....)
존 소총

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.