как публикуется ссылочный файл с содержимым действия сборки - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть проект ac #, который должен загрузить некоторые ресурсы yaml для работы, я установил их с помощью "build action": "content" и "copy to Output directory": "Copy if newer"

Чтобы загрузить их, я использую просто относительный путь, и все работает внутри проекта.

Я реализовал проект xunit, который загружает библиотеку, и все по-прежнему работает нормально.

Теперь я выпустил библиотеку на nugetи я пытаюсь сослаться на Asp.Net Core, но когда я пытаюсь загрузить мои файлы, приложение пытается найти их в неправильной папке:

Файлы ищутся по относительному пути от корневого aspПроект .net, но файлы находятся в C: \ Users \ [имя] \. nuget \ packages \ [имя пакета] \ [версия] \ content

Так что мне интересно, как я могу получить «контент»папка сборки в C #?

ОБНОВЛЕНИЕ: Я ПЫТАЮСЯ ОБЪЯСНИТЬ ЛУЧШЕ

У меня есть решение Visual Studio, мы называем его foo.sln и проект C #, которыймы называем foo.csproj

Проект является нестандартным 2.0 library и он предназначен для использования другими приложениями: cli, asp.net, core, wpf и т. д. *

Библиотека построена для мультиплатформенности, поэтому может работать в Windows, Mac и Linux

Внутри корня проекта foo есть папка, которую мы называем ее YamlDefinitions Внутри этой папки у нас есть много файлов .yaml, которые необходимо загрузить и проанализировать моей библиотекой foo.

Так что foo.csproj имеет что-то вроде:

<Content Include="YamlDefinitions\Definition1.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition2.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition3.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="YamlDefinitions\Definition4.yaml">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

Эти файлы являются неизменяемыми, поэтому я загружаю их как контент, а не как ресурс

Теперь внутри кода c # моей библиотеки foo, у меня есть:

var filePaths = Directory.GetFiles("YamlDefinitions", "*.yaml", SearchOption.TopDirectoryOnly)

foreach (var filePath in filePaths)
{
     using (var reader = new StreamReader(filePath))
     {
          // Load the stream
          var yamlStream = new YamlStream();
          yamlStream.Load(reader);
          yaml = yamlStream.Documents.FirstOrDefault();
     }
}

Этот код ищет, загружает и анализирует все файлы yaml, которые могут быть найдены в указанной папке.

Все выглядит нормально, поэтому теперь для тестирования я создаю объект xunit внутри foo.sln, мы называем это footest.csproj

Теперь я ссылаюсь на foo.csproj внутри footest.csproj

<ProjectReference Include="..\Foo\foo.csproj" />

Все тесты пройдены, поэтому я упаковываю библиотеку и публикую пакет nuget: foo.nuget

Теперь я хочу попробовать использовать пакет nuget, поэтому я создаю новую консольВ приложении с Net Core 2.2 мы называем это MyConsoleApp.csproj

Я устанавливаю свой пакет nuget foo.nuget:

 <PackageReference Include="Foo" Version="1.0.0"/>

пакет установлен и все файлы yaml помещены в

C:\Users\UserName\\.nuget\packages\Foo\1.0.0\content\YamlDefinitions

и

C:\Users\UserName\\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions

Файлы также видны внутри MyConsoleApp.csproj как связанные файлы, но физически их нет в проекте.

Теперь я запускаюmy MyConsoleApp.exe, и я получаю ошибку, потому что не могу найти эти файлы yaml, потому что приложение пытается загрузить их по тому же пути, что и MyConsoleApp.exe

Обходной путь: в Visual Studio я выбираю все файлы yamlкоторые связаны внутри MyConsoleApp.csproj, и я установил CopyIfNewer

Теперь в cproj visual studio добавлены следующие строки кода:

<Content Include="C:\Users\User\.nuget\packages\Foo\1.0.0\contentFiles\any\netstandard2.0\YamlDefinitions\Definition1.yaml">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>

Я снова запускаю MyConsoleApp.exe и все работает.

Этот обходной путь плох, потому что конечный пользователь должен иметь возможность использовать библиотеку nuget без указания вручную для копирования файлов.Если я выпускаю новую версию своей библиотеки, которая содержит новые определения, конечный пользователь не должен знать, что они должны быть включены в проект.

В любом случае, существует более серьезная проблема:

Я создаю новое приложение ASP.NET Core 2.2 MVC, мы называем его MyWebApp.csproj

Я устанавливаю Foo.nuget и пытаюсь его использовать.

Я установил вручную, чтобы скопировать все определения Yamlв выходной папке, и при сборке они автоматически копируются в MyWebApp\bin\Release\netcoreapp2.2\YamlDefinitions

Я запускаю веб-приложение и снова получаю сообщение об ошибке, потому что мой foo libray попытался найти файлы в MyWebApp\YamlDefinitions, но файлыв папке bin ничего не работает.

Как исправить библиотеку и опубликовать ее как nuget таким образом, чтобы все пользовательские приложения могли ее использовать?

1 Ответ

0 голосов
/ 18 декабря 2018

Я не могу найти функцию C #, которая извлекает папку nuget, в которой хранятся файлы контента, и я сомневаюсь, что она может существовать, но я нашел такой рабочий подход:

В foo.csproj файле вам нужно указатьчто каждый файл должен быть скопирован в выходную папку, это можно сделать с помощью:

<Content Include="YamlDefinitions\Definition1.yaml">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <PackageCopyToOutput>true</PackageCopyToOutput>
</Content>

Вам необходимо добавить PackageCopyToOutput, чтобы работать с nuget, к сожалению, этого нельзя сделать из интерфейса Visual Studio.и вам нужно редактировать .csproj вручную.

В C # вы должны использовать абсолютный путь, потому что относительный путь не одинаков во всех видах приложений (в .NET cli отличается от ASP.NET)

Таким образом, вы должны использовать такой код:

var directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "YamlDefinitions");
var filePaths = Directory.GetFiles(directory, "*.yaml", SearchOption.TopDirectoryOnly)

Где AppDomain.CurrentDomain.BaseDirectory возвращает выходной каталог, в который копируются файлы содержимого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...