Sellec
@Sellec
Кодер

Как работает подключение зависимостей с NetCore и NetStandard?

Этап 1.
Есть проект NetStandardLibrary на NetStandard 2.0. В него подключен в качестве зависимости пакет "System.IO.FileSystem.AccessControl" и объявлен единственный класс с методом Test:
using System;

namespace NetStandardLibrary
{
    public class Class1
    {
        public static bool Test(string folder)
        {
            try
            {
                var ds = new System.Security.AccessControl.DirectorySecurity(folder, System.Security.AccessControl.AccessControlSections.All);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}

Компилируем проект, на выходе получаем NetStandardLibrary.dll/NetStandardLibrary.pdb/NetStandardLibrary.deps.json.

Этап 2.
Есть проект TestNetFullApp (консольное приложение). Подключаем в него NetStandardLibrary как простую ссылку из солюшена, код приложения выглядит следующим образом:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestNetFullApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var d = NetStandardLibrary.Class1.Test(Environment.CurrentDirectory);
                Console.WriteLine("Hello World!");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.ReadLine();
        }
    }
}

Запускаем и получаем исключение (1). Как видно, среди загруженных сборок (2) не числится System.IO.FileSystem.AccessControl, подключенный в NetStandardLibrary. Собственно, его нет и в выходном каталоге приложения.
5b01839eaaff4945565952.png

Окей. В NetStandardLibrary ставим галку "Создать пакет Nuget при сборке", настраиваем в Visual Studio папку этого проекта как источник пакетов, подключаем пакет в TestNetFullApp. Запускаем - вуаля, ошибки нет, файл появился в выходном каталоге TestNetFullApp, т.к. System.IO.FileSystem.AccessControl была подтянута как зависимость для пакета NetStandardLibrary.

Хорошо, смотрим, что же это за файл. System.IO.FileSystem.AccessControl.dll весит 27.1кб.
Заглядываем в папку локального пользователя, далее ".nuget/packages", куда нынче механизмом PackageReference складируются все скачанные пакеты. Хм, что за диво? Почему библиотека весит 29.1кб?
5b0185cb9e9af135553254.png
Ищем в соседних папках и да! Искомый файл обнаруживается в соседней "\lib\net461". Осмотр через ILSpy подтверждает, что это идентичные библиотеки с атрибутами TypeForwardedTo внутри. А вот копия в "\lib\netstandard2.0" этих атрибутов не имеет. Что, собственно, подтверждается экспериментом - если подпихнуть сборку из "\lib\netstandard2.0" приложению TestNetFullApp, то вылетает исключение PlatformNotSupportedException.

Этап 3.
Создаем консольное приложение TestNetCoreApp и подключаем NetStandardLibrary как проект из солюшена.
Запускаем - всё работает. Причем сборка System.IO.FileSystem.AccessControl.dll была подключена из папки ".nuget/packages".
5b018756e58d8524360076.png-----------------------------------------------------------------------
В общем, в связи с этим возник ряд вопросов по работе самого механизма подключения зависимостей в NetStandard и .Net Core.
1) Где можно почитать подробно о том, как это работает?
2) Почему приложение TestNetFullApp ссылается на сборку из папки "\lib\net461" вместо "\lib\netstandard2.0"? NetStandard работает как интерфейс и ищет именно сборку на той платформе, на которой запущено приложение?
3) Если ответ на вопрос в предыдущем пункте "да", то как же создать независимую от Nuget сборку под NetStandard со всеми вариантами зависимых сборок (той же System.IO.FileSystem.AccessControl.dll), чтобы оно работало без проблем на NetFramework, NetCore, NetStandard путем просто подключения NetStandardLibrary как reference.
3.1) Уточнение к вопросу. Дело в том, что в одном из проектов формируется сборка, устанавливаемая в GAC, она подключается в Design-time в Visual Studio для работы с Razor. Если переводить её на NetStandard, то возникает необходимость либо иметь все сборки, от которых она зависит, в GAC, либо пользоваться Costura.Fody (включение зависимых сборок в тело основной сборки в виде embedded resources). Второй вариант очень удобен, все зависимости подгружаются автоматом при загрузке основной сборки. Но с NetStandard это не прокатывает - в качестве зависимости цепляется файл из "\lib\netstandard2.0", а приложению нужен не он.
4) Что будет, если я запущу TestNetCoreApp в профиле другого пользователя, у которого нет скачанных пакетов в ".nuget/packages"? Они подтянутся автоматом? Если да, то что должно быть установлено в системе?
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
Вы столкнулись с библиотекой, которая имеет различные версии под разные операционные системы (в нюгете это называется runtimes). Констатировать это можно по наличию папки runtimes в корне nuget-пакета. Та сборка которую вы видите в lib\netstandard2.0 (весов 29 кб) редиректит типы на сборку для конкретного рантайма (ЕМНИП).
1) Где можно почитать подробно о том, как это работает?

Начните отсюда: https://natemcmaster.com/blog/2016/05/19/nuget3-ri...
NetStandard работает как интерфейс и ищет именно сборку на той платформе, на которой запущено приложение?

Да.
то как же создать независимую от Nuget сборку

Что значит независимую от NuGet? В чём вы видите зависимость?
4) Что будет, если я запущу TestNetCoreApp в профиле другого пользователя, у которого нет скачанных пакетов в ".nuget/packages"?

https://docs.microsoft.com/en-us/dotnet/core/tools... :
Starting with .NET Core 2.0, you don't have to run dotnet restore because it's run implicitly by all commands, such as dotnet build and dotnet run, that require a restore to occur.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы