Не удается решить проблему ссылки на сборку без frameworkAssemblies


я пытаюсь проверить, что Протокол Буферы будет работать с новыми портативными средами выполнения от ASP.NET команда и в идеале большинство других современных сред. Сборка 3.0.0-alpha4 была создана некоторое время назад с использованием profile259, поэтому я ожидал бы, что в некоторых случаях потребуются некоторые изменения, но я подумал, что попробую. Я в курсе сообщение Орена Новотны о таргетинге .NET Core, и ожидается, что придется внести некоторые изменения в Google.Файл nuspec Protobuf, но ошибка, с которой я сталкиваюсь, ставит меня в тупик.

версия DNX: 1.0.0-rc1-update1

сценарий, который я сейчас пытаюсь протестировать, - это консольное приложение, предназначенное для dnx451. У меня есть очень простой пример приложения:

using Google.Protobuf.WellKnownTypes;
using System;

public class Program
{
    public static void Main(string[] args)
    {
        Duration duration = new Duration { Seconds = 100, Nanos = 5555 };
        Console.WriteLine(duration);
    }
}

... и маленький project.json:

{
  "compilationOptions": { "emitEntryPoint": true },
  "dependencies": { "Google.Protobuf": "3.0.0-alpha4" },

  "frameworks": {
    "dnx451": { }
  }
}

обратите внимание, что я даже не используя dnxcore* вот-по иронии судьбы, я получил это работать без проблем.

dnu restore работает отлично;dnx run выдает:

ошибка: c:UsersJonTestProjectsprotobuf-coreclrsrcProtobufTestProgram.cs (9,9): DNX,Version=v4.5.1 ошибка CS0012: тип 'Object' определен в сборке, на которую нет ссылки. Необходимо добавить ссылку на систему сборки.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

следующие изменения приводят к той же ошибке:

  • явное добавление a зависимость от "System.Runtime": "4.0.0" на в рамках
  • явное добавление зависимости к "System.Runtime": "4.0.0-beta-23109" на dependencies Раздел для фреймворка, а также для 4.0.10-beta-*,4.0.20-beta-* и 4.0.21-beta*.
  • добавление зависимостей к System.Runtime в пакете NuGet (локально) и перестроение против этого - project.lock.json был обновлен, чтобы включить систему.Время выполнения v4.0. 0, но произошла та же ошибка
  • то же самое, включая A в пакете, как а также зависимости

шаги сделал работа (самостоятельно, а не dependencies записи), но меня смущают:

  • изменение Console.WriteLine называть просто Console.WriteLine("foo") (но никаких других изменений)
  • изменение типа duration переменная object вместо Duration
  • удаление всех подсказок буферов протокола полностью, а вместо этого с помощью TimeSpan или подобное
  • добавить следующий проект.json в :

    "frameworkAssemblies": {
      "System.Runtime": ""
    }
    

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

я полагаю, что если бы я мог найти способ сделать dependencies запись работы, я мог бы добавить эту зависимость в Протокол буферизует себя, что было бы хорошо, но как имеющее зависимость от системы.Время выполнения v4.0.0 в проекте.файл блокировки, похоже, не помогает, я должен что-то упустить :(

3 53

3 ответа:

так что если вы прищуритесь и посмотрите на проект.json, это в основном nuspec с небольшим количеством goop, чтобы описать, какие параметры компиляции и источники необходимы для создания проекта. У Nuspecs сегодня есть 2 раздела,frameworkAssemblies для "встроенных" вещей и dependencies для других зависимостей nuget. Здесь он имеет то же самое значение. Когда вы используете что-то из "фреймворка", его нужно указать в frameworkAssemblies vs является зависимостью пакета nuget.

сейчас на особенности:

при использовании библиотеки на основе PCL или .NET Core в .NET Framework ссылки относятся к ссылочным сборкам (иногда называемым сборками контрактов). Некоторые примеры таких вещей, как System.Runtime,System.Threading etc. При использовании проектов на основе MSBUILD, есть задача, которая выполняется, которая в основном автоматически добавляет все на System.* ссылки на компилятор C#, чтобы избежать этого беспорядка. Эти сборки называются фасадами в .NET Framework. Неудачник часть в том, что он добавляет все из них, даже если они не используются. Зависимость от System.Runtime является триггером для этого поведения (при запуске на основе csproj файлов .NET Framework).

причина, по которой добавление ссылки на один и тот же пакет не работает, заключается в том, что папка .NET Framework (net4*) для этих сборок контрактов (например, System.Runtime), в них нет библиотек DLL. Если вы посмотрите на эти папки, вы увидите пустой . Причина этого заключается в том, что когда вы объявляете пакет nuget с frameworkAssembly ссылка System.Runtime, системы проекта msbuild не удается установить его (очень сложная ошибка и проблема проектирования).

это, вероятно, сделало вещи более размытыми...

Я принял ответ Дэвида Фаулера причиной почему все это произошло. Теперь с точки зрения того, что я должен do об этом, похоже, мне нужно добавить frameworkAssemblies элемент в файле nuspec для Google.Protobuf:

<package>
  <metadata>
    ...
    <frameworkAssemblies>
      <frameworkAssembly assemblyName="System.Runtime" targetFramework="net45" />
    </frameworkAssemblies>
  </metadata>
  ...
</package>

Это frameworkAssembly ссылка затем заканчивается в project.lock.json в клиентском проекте, и все хорошо.

однако, судя по другому комментарию Дэвида ("мы собираемся посмотреть на исправление этого"), мне может не понадобиться делать все равно...

мне кажется, что ваша проблема существует только потому, что вы выбрали консольное приложение вместо "ASP.NET веб-приложение" / "ASP.NET 5 шаблонов" / "пусто". Я сделал простой тест использования пустой шаблон, добавили "Google.Protobuf": "3.0.0-alpha4" от NuGet и, наконец, просто изменен Startup.cs так что он использует Google.Protobuf.WellKnownTypes:

  • добавил using Google.Protobuf.WellKnownTypes;
  • добавил var duration = new Duration { Seconds = 100, Nanos = 5555 }; внутри Configure
  • изменен await context.Response.WriteAsync("Hallo World!"); до await context.Response.WriteAsync(duration.ToString());

финальный код из Startup.cs:

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.DependencyInjection;
using Google.Protobuf.WellKnownTypes;

namespace ProtobufTest
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {
            app.UseIISPlatformHandler();

            var duration = new Duration { Seconds = 100, Nanos = 5555 };

            app.Run(async context =>
            {
                await context.Response.WriteAsync(duration.ToString());
            });
        }

        // Entry point for the application.
        public static void Main(string[] args) => WebApplication.Run<Startup>(args);
    }
}

результат ASP.NET 5 приложение отображается успешно 100.5555s в веб-браузере.

вы можете скачать демо-проект из здесь.

обновление: я проанализировал проблему с чистым консольным приложением DNX, которое использует код и может найти причину проблема duration.ToString() метод, который работает внутри ASP.NET среда, но не в чистом консольном приложении. Этот причина проблемы интересна, и я пытаюсь исследовать, но я хотел бы поделиться своими текущими результатами с другими

я мог бы сделать работу следующий код:

using Google.Protobuf.WellKnownTypes;
using System;

namespace ConsoleApp3
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var duration = new Duration { Seconds = 100, Nanos = 5555 };
            Console.WriteLine("{0}.{1:D4}s", duration.Seconds, duration.Nanos);
        }
    }
}

можно скачать рабочий проект от здесь.

я прокомментировал дополнительно строку

//[assembly: Guid("b31eb124-49f7-40bd-b39f-38db8f45def3")]

на AssemblyInfo.cs чтобы не было ненужной ссылки на "Microsoft.CSharp", которые имеют много других ссылок. Элемент project.json содержится в демонстрационный проект:

{
  ...

  "dependencies": {
    "Google.Protobuf": "3.0.0-alpha4"
  },

  "frameworks": {
    "dnx451": { },
    "dnxcore50": {
      "dependencies": {
        "System.Console": "4.0.0-beta-23516"
      }
    }
  }
}

кстати, в том числе "System.Console": "4.0.0-beta-23516" на "dnxcore50" часть "frameworks" не требуется, поскольку Console пространство имен (для Console.WriteLine) существуют в mscorlib на DNX 4.5.1. Если бы кто-то попытался добавить "System.Console": "4.0.0-beta-23516" на уровне common зависимости один получить ошибку с начинается с текста

ошибка CS0433 тип "консоль" существует в обеих системах.Приставка, Версия=4.0.0.0, культуры=нейтральный, значения PublicKeyToken=b03f5f7f11d50a3a и 'mscorlib, Version=4.0.0.0, Culture=нейтральный, ConsoleApp3 значения PublicKeyToken=b77a5c561934e089'.DNX 4.5.1

обновлено 2: можно заменить строку

Console.WriteLine("{0}.{1:D4}s", duration.Seconds, duration.Nanos);

до

Console.WriteLine((object)duration);

чтобы заставить его работать. Просто использование Console.WriteLine(duration); или var str = duration.ToString(); выдает ошибку, которую вы описали.

обновлено 3: я проверил, что код duration.ToString() звонки строки что использовать в линии для форматирования. Кажется, что код duration.ToString() делает действительно то же самое, что ((object)duration).ToString() на WellKnownTypes типы (например,Duration).

последнее замечание, которое я считаю важным. Описанная проблема существует только для dnx451 (или dnx452 или dnx46). Если бы можно было удалить строки

"dnx451": { },

с "frameworks" часть project.json тогда программа будет компилироваться только для DNX Core 5.0 ("dnxcore50"). Можно легко проверить, что у вас не будет никаких проблем больше.

обновлено 4: наконец-то я нашел очень простое решение проблемы: нужно просто добавить "Microsoft.AspNet.Hosting": "1.0.0-rc1-final" зависимость от проекта:

{
  "dependencies": {
    "Google.Protobuf": "3.0.0-alpha4",
    "Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
  }
}

это следует для загрузки многих ненужных DLL, но теперь зависимости будут правильно решены.

окончательный проект может быть скомпилирован без каких-либо проблем для dnx451 и dnxcore50. Я интерпретирую результаты следующим образом: "Google.Protobuf" работают с обоими dnx451 и dnxcore50, но автоматическое разрешение зависимостей RC1 по-прежнему глючит, и он не может правильно решить некоторые необходимые зависимости "Google.Protobuf".

причины добавления непосредственно ненужные "Microsoft.AspNet.Hosting": "1.0.0-rc1-final" ссылка может рассматриваться только как временное решение. Я думаю, что разрешение зависимостей используется в ASP.NET 5 и DNX все еще глючит. Я написал некоторое время до вопрос, который все еще открыт. Проблема дает пример, когда решение прямой включенная зависимость может обеспечить другое результаты в виде зависимостей решается dnu restore. Именно по этой причине я начал сравнивать зависимость код, который я отправил вам изначально с зависимостями неработающего проекта. После некоторых тестов я нашел обходной путь и уменьшил его до единственной зависимости:"Microsoft.AspNet.Hosting": "1.0.0-rc1-final".