Runtime: Должна ли быть версия Reflection.Emit для .Net Standard 2.0?

Созданный на 27 апр. 2018  ·  58Комментарии  ·  Источник: dotnet/runtime

System.Reflection.Emit не является частью .Net Standard, но есть пакеты, позволяющие использовать его из стандартной библиотеки .Net (в частности, System.Reflection.Emit и System.Reflection.Emit.Lightweight ). Но у этих пакетов нет версии .Net Standard 2.0, только версии .Net Standard 1.x.

Это имеет некоторые последствия:

  • Библиотеки .Net Standard 2.0 не могут использовать typeBuilder.CreateType() (хотя этот код работает как в .Net Framework 4.6.1, так и в .Net Core 2.0) и вместо этого должны использовать typeBuilder.CreateTypeInfo().AsType() . Возможно, существуют и другие подобные API.
  • Библиотеки .Net Standard 2.0, которые хотят использовать Reflection.Emit, по-прежнему должны использовать пакеты System. * В стиле .Net Standard 1.x.

Эти проблемы будут решены, если в пакеты Reflection.Emit будет добавлена ​​версия .Net Standard 2.0. Стоит ли это делать?

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

area-System.Reflection.Emit question

Самый полезный комментарий

Всем спасибо за отзывы. Основываясь на огромных отзывах, мы повторно включили последнюю версию существующих пакетов:

https://www.nuget.org/packages/System.Reflection.Emit/4.3.0
https://www.nuget.org/packages/System.Reflection.Emit.Lightweight/4.3.0

Однако, как упоминалось ранее в этом потоке, эти пакеты утверждают, что они совместимы с netstandard1.1, но это ложь. Они будут работать только на .NET Core и .NET Framework. Так что, если вы используете их из библиотеки netstandard, ожидайте, что эта библиотека выйдет из строя, если она будет запущена в любой другой реализации .NET Standard.

У нас все еще нет отличного решения для их поддержки на netstandard2.0, но владельцы ( @AtsushiKan @joshfree) System.Relfection.Emit будут пытаться найти более долгосрочное решение.

Все 58 Комментарий

@ericstj @weshaggard знаете ли вы, что это сделано намеренно или по недосмотру?

Это было сделано намеренно. Для таких библиотек, которые имеют неровную поддержку и не имеют переносимой реализации, мы прекратили отправку пакетов. Ожидается, что вы нацелитесь на конкретную структуру, если вам это нужно. Для некоторых мы вернули пакеты с фугасами (бросая реализации на некоторых платформах). Люди могут предложить, чтобы мы добавили его обратно, но этот, в частности, вызывал серьезные споры в прошлом из-за отсутствия поддержки всех основанных на AOT фреймворков .net. / cc @terrajobst

@ericstj

Ожидается, что вы нацелитесь на конкретную структуру, если вам это нужно.

Как я должен об этом узнать? Насколько я могу судить, Reflection.Emit не сообщается платформой-compat. И когда я Google «отражение Испустите .Net Стандарт», единственный результат на первой странице говорить о том, следует ли использовать его таким образом является чирикать с июля 2017 года по @terrajobst предполагая , что вы должны сделать это (возможно , ситуация изменилась с тех пор ?).

Я позволю @terrajobst ответить на это, возможно, он думал о функции nuget gaurdrails, которая была в пакетах 1.x и 1.x. С ними у нас были неровные реализации и поддержка времени сборки для обмена сообщениями, которые не поддерживаются. Я не особо склоняюсь к тому или иному здесь, просто объясняю, как все работает в данный момент. Я думаю, что если мы сможем получить согласие людей на добавление пакета с платформой, не поддерживающей реализацию, мы сможем это сделать.

FWIW все, что доступно во фреймворке, но не в netstandard или в библиотеке / пакете с активом netstandard, означает, что вам нужно настроить таргетинг на фреймворк, чтобы получить его. Это все, что я имел в виду в своем ожидаемом комментарии.

@ericstj

все, что доступно в структуре, но отсутствует в netstandard или в библиотеке / пакете с активом netstandard, означает, что вам нужно настроить таргетинг на структуру, чтобы получить это. Это все, что я имел в виду в своем ожидаемом комментарии.

Но здесь пакет (с активами .Net Standard 1.x) действительно существует. Я не думаю, что можно просто прекратить обновлять пакет и предположить, что люди больше не будут его использовать. По крайней мере, у вас должна быть документация, объясняющая ситуацию.

Самая большая проблема с System.Reflection.Emit заключается в том, что у нас нет способа предоставить библиотеку стандартным способом из-за TypeInfo (см. Https://github.com/dotnet/corefx/issues/14334). Существующий пакет нацелен на netstandard1.1, но это ложь и будет работать только на .NET Framework и .NET Core из-за тесной связи, которая у нас есть. Мы взломали его для работы, применив трюки InternalsVisibleTo, чтобы предоставить ему доступ к конструкторам TypeInfo, но тот же самый трюк не позволяет ему работать на общей платформе .NET Standard. Мы решили не распространять ошибку дальше, взломав netstandard2.0 таким же образом, а вместо этого прекратили выпуск пакета и сделали его специфичным для платформы.

Спасибо, что подняли вопрос @svick, и мы должны использовать эту проблему, чтобы задокументировать проблему с пакетом.

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

Это разумное предложение. Я просто исключил все версии https://www.nuget.org/packages/System.Reflection.Emit/ и https://www.nuget.org/packages/System.Reflection.Emit.Lightweight

Это очень нужно. Невозможность создавать и сохранять сборки в настоящее время является моим самым большим препятствием для обновления до .NET Core в dotnet / corefx # 1, и мне бы очень хотелось, чтобы повышение скорости этого очень фундаментального API стало более приоритетным, чем работа над новыми функциями .

@masonwheeler просто для вызова, вы можете использовать Reflection.Emit, если вы пишете приложение или библиотеку .NET Core, вы просто не можете использовать его при написании стандартной библиотеки .NET в настоящее время.

@weshaggard ты уверен? Я только что проверил репо, и оказалось, что AssemblyBuilder.Save не только еще не реализовано, но и вообще не существует в Core! (Возможно, я ошибаюсь; я использую свой телефон, а мобильный интерфейс GitHub не самый лучший, но он выглядит именно так.)

@masonwheeler, вы правы, что мы не поддерживаем AssemblyBuilder.Save в .NET Core, который отслеживается другой проблемой https://github.com/dotnet/corefx/issues/4491.

Вот оно! Я думал, что видел эту проблему раньше, но поиск показал только эту. :П

Но да. Без возможности фактически выдавать свои результаты вы не можете сказать, что можете использовать Reflection.Emit в Core. ☹️

@weshaggard до того, как пакет System.Reflection.Emit.Lightweight был исключен из списка на nuget.org, можно было получить пакет Selenium.WebDriver в PowerShell 5 (для .Net Framework) и PowerShell Core 6 (для .Net Core 2.0) в Windows 10 используя следующую команду: Install-Package Selenium.WebDriver -Destination $ PSScriptRoot -Force -ForceBootstrap

Теперь эта команда не может загрузить все зависимости пакета Selenium для обеих версий PowerShell. Это не удается, так как пакет System.Reflection.Emit.Lightweight.4.3.0 отсутствует в списке nuget.org.
Ошибка: Install-Package: невозможно найти зависимые пакеты (System.Reflection.Emit.Lightweight)

Не могли бы вы посоветовать, как решить эту проблему?

@SergeyKhutornoy вы вызываете "Install-Package" в VS из консоли диспетчера пакетов? Если это так, пакет для меня правильно устанавливается. Если вы вызываете Install-Package из Powershell, это другой вид управления пакетами. На самом деле я просто пробовал это локально и получаю другую ошибку (Install-Package: не найдено совпадений для указанных критериев поиска и имени пакета Selenium.WebDriver). Я не знаком с этой системой управления пакетами, поэтому я не знаю, как это обойти. Вы можете попробовать сначала явно установить System.Reflection.Emit.Lightweight 4.3.0, а затем посмотреть, работает ли он. Если это не сработает, по какой причине вы не можете использовать инструменты VS или nuget для установки пакета?

Исключение этого пакета из списка является ошибкой, а отсутствие версии .NET Standard 2.0 - ошибкой.

Мы собираемся выпустить основную новую версию нашего продукта NServiceBus, и мы нацелены на netstandard2.0 . У нас также есть зависимость от System.Reflection.Emit и System.Reflection.Emit.Lightweight. Изначально я намеревался настроить таргетинг на .NET Framework и .NET Core по отдельности, но беседа в твиттере с @terrajobst в сочетании с обнаружением, что эти пакеты доступны, заставили меня изменить планы и вместо этого нацелиться на netstandard2.0 .

Я не против того, что не могу так много сохранять динамические сборки - я всегда могу протестировать логику в TFM .NET Framework, но DynamicMethod невероятно полезен и очень широко используется для генерации преобразователей отражений, делегатов преобразователей и т. Д. .System.Reflection.Emit. * Пакеты имеют более 20 000 000 загрузок.

Пожалуйста, верните способ ссылки на DynamicMethod в библиотеках netstandard2.0.

Как мы используем DynamicMethod в .NET Core теперь, когда его нет в списке как пакет?

@danielcrenna Вам не нужен пакет для использования DynamicMethod в .Net Core, поскольку он встроен. Пакет нужен только для использования в .Net Standard.

Я мог бы создать свою среду выполнения (которая уже выпущена) на .netstandard 2.0, используя System.Reflection.Emit.Lightweight 4.3, поскольку я использую DynamicMethod. Теперь я вижу, что процесс сборки извлекает пакет из автономного кеша, а не из nuget. ~ Если автономный кеш закрыт, я не могу снова собрать код для .NETstandard. ~ (Размещение кеша заставляет процесс сборки снова вытащить пакет, так как пакет все еще существует, хотя и не указан в списке, поэтому это не демонстрационная программа технически, хотя семантически).

Глядя здесь: https://apisof.net/catalog/System.Reflection.Emit.DynamicMethod, какой вывод я должен сделать? Что это в NS1.6? Или в каком-то промежуточном измерении, где допустимы «расширения платформы»?

Итак, iow: поскольку я нацелен на .netstandard2.0 и использую DynamicMethod, я могу сделать ссылку на System.Reflection.Emit.Lightweight, хотя он не указан и поддерживается в ns1.6 (?), Но это действительно не так: кажется, что ответственность, поскольку теперь я полагаюсь на пакет, который не внесен в список (и тогда я должен надеяться, что незарегистрированные пакеты будут храниться там до конца времени). Печальная вещь: нет альтернативы, кроме зависимости от пакета, не указанного в списке, который возможен только потому знает точное имя.

// @terrajobst

Чтобы добавить: EF Core 2.1 зависит от Castle.Core (https://www.nuget.org/packages/Castle.Core/) для своих прокси, который зависит от System.Reflection.Emit.

Разве не разумно, если бы все участники снова пополнили этот пакет (и Emit.Lightweight)?

@FransBouma, строго говоря, у EF Core Proxies есть зависимость, а не у самого EF Core. Но все равно это бардак.

Фактически _FirebirdClient_ зависит от _System.Reflection.Emit_. А что теперь делать, да?

Хотя понятно, что полные платформы AOT не могут позволить создавать новые типы во время выполнения, больше удивляет то, что мы не можем поддерживать System.Reflection.Emit.Lightweight на этих платформах.
LambdaExpression.Compile() работает на всех платформах, даже если он интерпретируется на AOT.

Я являюсь автором библиотеки LightInject DI, которая использует Reflection.Emit и DynamicMethod для генерации кода во время выполнения. Все было хорошо, пока не начали появляться другие платформы. SilverLight, WinRT, iOS и так далее. Так что делать? Я сделал "прокладку" DynamicMethod чтобы коды операций переводились в выражения. Между кодами операций и выражениями существует своего рода связь 1-1, так что это совсем не сложно.

Взгляните здесь на реализацию.
https://github.com/seesharper/LightInject/blob/a01be40607761d9b446dc4acad37d7f717742975/src/LightInject/LightInject.cs#L4483

Обратите внимание, что я не использую все коды операций. Только те, которые мне нужны.

Я считаю, что это должно быть возможно сделать для всех кодов операций, а затем включить МНОГО библиотек, чтобы по-прежнему ориентироваться на netstandard2.0. Большинство библиотек, использующих Reflection.Emit, не генерируют новые типы. Они просто генерируют код через DynamicMethod

Также обратите внимание, что DynamicProxy, Moq и другие библиотеки, которые генерируют типы во время выполнения, не могут нацеливаться на netstandard2.0 . Они должны быть netcoreapp поскольку они в основном полагаются на AssemblyBuilder с друзьями.
Итак, суть в том, что пакет System.Reflection.Emit.Lightweight никогда не может быть полностью удален из NuGet как netstandard2.0 . Это была бы история LeftPad снова и снова

Мои два цента

Есть ли где-нибудь список TFM, которые действительно поддерживают System.Reflection.Emit ? Я только что добавил в свой проект явные TFM net45 и netcoreapp2.0 , но я уверен, что мне не хватает некоторых.

@jbogard Все TFM полной инфраструктуры должны быть хороши в дополнение к TFM netcoreapp. Это в AutoMapper?

Это кажется плохо продуманным и обнародованным решением с далеко идущими последствиями, которое, по-видимому, было принято при очень небольшом участии сообщества, на которое оно влияет, что удивительно, учитывая, что пакеты имеют 22 миллиона загрузок. Разве это не требует какого-то анализа потенциального воздействия на всех, кто в настоящее время от него зависит?

ServiceStack ссылается на теперь исключенные пакеты Reflection.Emit в ServiceStack.Text, который является базовым пакетом зависимостей, который фактически используется в netstandard2.0 и net45 , принудительный таргетинг на платформу .netcore нарушит каждую отдельную зависимость и каждый проект netstandard2.0 использующий ее, т.е. предпочтительную целевую структуру для создания кроссплатформенности. сборки, поддерживающие .NET Framework и .NET Core.

Итак, каковы теперь рекомендации для пакетов, использующих Reflection.Emit? Прекратить публиковать сборки .NET Standard 2.0 и сказать всем, что они больше не могут создавать сборки .NET Standard 2.0 для своих библиотек и проектов?

Предыдущее решение для использования API-интерфейсов .NET Standard, которые не реализуют API, заключалось в выдаче PlatformNotSupportedException исключений времени выполнения, почему именно это решение не здесь?

@seesharper да, я добавил те, но другие могут не документации по API перечислено больше, но чего еще может не хватать? Это полный список возможных TFM, поддерживающих API? Как насчет, скажем, xamarinxboxone ?

Я реорганизовал свой код DynamicMethod / ILGenerator, который я использовал для создания методов установки для свойств во время выполнения с помощью решения Lambda.Compile (), поэтому зависимость от Reflection.Emit исчезла, однако мне пришлось потратить на это 3-4 часа. которые я хотел бы потратить на другие вещи. Но, увы, это жизнь, когда все «движется быстро и часто ломается», я думаю?

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

Я полностью согласен с @mythz и другими здесь, он плохо передается, и с 22 миллионами загрузок это было глупое решение с далеко идущими последствиями.

@mythz Я не знаю, как вы его используете, но для моих вещей мне пришлось вернуться к флагам функций #if, чтобы удалить функциональность на платформах, которые не поддерживают типы сборки на лету (в моей библиотеке, будучи возможность сопоставления с интерфейсом, и я создаю прокси на лету).

@jbogard Мы используем логический флаг Env.SupportsEmit чтобы определить во время выполнения, поддерживает ли платформа Reflection.Emit, если она используется, в противном случае мы возвращаемся к скомпилированным выражениям. В этой заметке было бы полезно, если бы был флаг Platform.SupportsEmit который каждый мог бы использовать, чтобы проверить, поддерживает ли работающая платформа Reflection.Emit.

Директива #if потребует создания нескольких сборок платформы, что станет причиной критического изменения для всех зависимых пакетов и проектов, нацеленных на .netstandard2.0 , поскольку они также требуют .netstandard2.0 зависимостей.

Просто для дальнейшего обсуждения я хотел бы убедиться, что мы все находимся на одной странице, когда речь идет о разнице между System.Reflection.Emit и System.Reflection.Emit.Lightweight .

Этот вопрос фактически следовало разделить на два отдельных вопроса. 😄

  • Должна ли быть версия Reflection.Emit для .Net Standard 2.0?
  • Должна ли быть версия System.Reflection.Emit.LightWeight для .Net Standard 2.0?

System.Reflection.Emit

Этот пакет содержит AssemblyBuilder и связанные с ними классы, необходимые для создания сборок / типов во время выполнения.
Проблема с этим пакетом заключается в том, что его никогда не следует размещать в NuGet как пакет netstandard , поскольку создание новых типов во время выполнения не может поддерживаться на полных платформах AOT.
Я предполагаю, что Microsoft добавила это как пакет netstandard , чтобы упростить переход с полной платформы на библиотеки .Net Core и netstandard . Оглядываясь назад, это не самая лучшая идея.
Подход «приманка и подмена» (понимаемый примерно пятью людьми во всем мире) также не является отличным решением.

System.Reflection.Emit.LightWeight

Этот пакет содержит DynamicMethod, который позволяет динамически компилировать код БЕЗ создания новых типов. «Динамический метод» - это в основном статический метод, для которого мы можем создать делегат, используемый для вызова метода.
LambdaExpression.Compile - это в основном то же самое, и если мы посмотрим на реализацию на полной структуре, мы увидим, что она фактически использует DynamicMethod под покровом.
Дело в том, что LambdaExpression.Compile() работает на всех платформах с использованием интерпретации на AOT. Из-за этого нет причин, по которым мы не можем создать пакет System.Reflection.Emit.LightWeight , который равен netstandard используя технику, которую я описал ранее в этом потоке.

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

Я предлагаю сделать попытку опубликовать System.Reflection.Emit.LightWeight как настоящий пакет netstandard и продолжать настаивать на netcoreapp когда дело доходит до System.Reflection.Emit .

@seesharper Насколько мне известно, Reflection.Emit (включая Reflection.Emit.Lightweight) в основном используется для повышения производительности. Но если бы вы реализовали Reflection.Emit.Lightweight с помощью интерпретатора IL, его производительность, вероятно, была бы очень плохой. Так что я не уверен, что поддержка режима интерпретации IL в Reflection.Emit.Lightweight будет оправдана.

Также странно, что System.Reflection.Emit.ILGenerator все еще присутствует в списке (https://www.nuget.org/packages/System.Reflection.Emit.ILGeneration), поскольку это пакет netstandard1.6, однако ILGenerator не имеет реализации UWP (https://apisof.net/catalog/System.Reflection.Emit.ILGenerator).

Айоу: немного беспорядка, понятно?

@seesharper Хорошее предложение.

@svick Я не думаю, что это достаточное основание для его сокращения. Для предметно-ориентированных языков требуется возможность создания кода во время выполнения. DSL достаточно часто возникают в крупных проектах ( десятое правило Гринспана ), и лучше, если каждому писателю не придется изобретать и писать для него свой собственный интерпретатор (с использованием регулярного отражения и Invoke ). Если это стандартный компонент, по крайней мере, "неформально определенные и содержащие ошибки" части правила будут смягчены. Что касается производительности реализации AOT-таргетинга, она не обязательно должна быть интерпретатором IL. Даже на платформах, которые не позволяют процессу создавать исполняемые страницы памяти, можно скомпилировать динамические методы в поточный код, как это делают многие реализации FORTH, а для небольших динамических методов, где «тело метода» помещается в пару строк кэша, накладные расходы времени выполнения должны быть довольно низкими.

Проблема с этим пакетом заключается в том, что его никогда не следует помещать в NuGet в качестве пакета netstandard, поскольку создание новых типов во время выполнения не может поддерживаться на полных платформах AOT.

Не согласен. Основные платформы .NET Core и .NET Framework поддерживают его, просто потому, что среды AOT не должны препятствовать тому, чтобы они могли поддерживать основные платформы .NET, нацеленные на netstandard2.0 .

Стало ли это стратегией развития .NET Standard? API-интерфейсы, не поддерживаемые в средах AOT, теперь будут удалены? Значит, больше не будет PlatformNotSupportedException Исключений, API-интерфейсы будут перемещены, вместо того, чтобы возвращаться к подмножеству PCL? Или мы будем непоследовательными и выборочно уменьшим поверхность API для некоторых функций, но продолжим добавлять другие?

Поддержка пересечения API-интерфейсов с наименьшим общим знаменателем - вот что сделал PCL и привел к ужасному опыту разработки, который заставил использовать технику приманки и переключения PCL и делегирование нескольким реализациям для конкретных платформ, что является всеми инвестициями, которые мы выбросили, когда перешли на. NET Standard.

Лучшим решением было существующее (особенно, поскольку его удаление сейчас является разрушительным и ломающим изменение его переходных зависимостей), которое позволяет нам использовать Reflection.Emit на всех платформах, которые его поддерживали, и при этом необходимо реализовать резервный вариант для тех, кто этого не делает. . Удаление возможности использовать Reflection.Emit в .NET Standard означает, что библиотеки, которые его используют, больше не могут использовать .NET Standard. В чем вообще смысл, если мы не можем использовать функции, общие для .NET Core и .NET Framework, в абстракции, не зависящей от платформы? Это просто добавило бы ненужных абстракций / путаницы / сложности в экосистему .NET без каких-либо преимуществ.

Всем спасибо за отзывы. Основываясь на огромных отзывах, мы повторно включили последнюю версию существующих пакетов:

https://www.nuget.org/packages/System.Reflection.Emit/4.3.0
https://www.nuget.org/packages/System.Reflection.Emit.Lightweight/4.3.0

Однако, как упоминалось ранее в этом потоке, эти пакеты утверждают, что они совместимы с netstandard1.1, но это ложь. Они будут работать только на .NET Core и .NET Framework. Так что, если вы используете их из библиотеки netstandard, ожидайте, что эта библиотека выйдет из строя, если она будет запущена в любой другой реализации .NET Standard.

У нас все еще нет отличного решения для их поддержки на netstandard2.0, но владельцы ( @AtsushiKan @joshfree) System.Relfection.Emit будут пытаться найти более долгосрочное решение.

@svick

Насколько мне известно, Reflection.Emit (включая Reflection.Emit.Lightweight) в основном используется для повышения производительности. Но если бы вы реализовали Reflection.Emit.Lightweight с помощью интерпретатора IL, его производительность, вероятно, была бы очень плохой. Так что я не уверен, что поддержка режима интерпретации IL в Reflection.Emit.Lightweight будет оправдана.

Насколько я понимаю, LambaExpression.Compile() и его выполнение интерпретируются на платформах AOT, и, следовательно, это не должно быть хуже для System.Reflection.Emit.LightWeight .
Есть много библиотек, использующих этот пакет, и наличие «настоящего» пакета netstandard2.0 внезапно позволило бы этим пакетам запускаться на вашем iPhone, не заставляя разработчиков этих пакетов переписывать свой код для соответствия различным платформам. Производительность будет снижена, но она будет работать так же, как сегодня, с LambdaExpression.Compile()

@mythz

Стало ли это стратегией развития .NET Standard? API-интерфейсы, не поддерживаемые в средах AOT, теперь будут удалены? Значит, больше не будет исключений PlatformNotSupportedException, API-интерфейсы будут перемещены, вместо того, чтобы возвращаться к подмножеству PCL? Или мы будем непоследовательными и выборочно уменьшим поверхность API для некоторых функций, но продолжим добавлять другие?

IMHO, бросок PlatformNotSupportedException - это еще одно проявление подмножества API, которое мы видели с PCL. Как и в случае с System.Reflection.Emit.LightWeight , мы действительно можем его реализовать, и нет причин бросать PlatformNotSupportedException . Я, однако, согласен с тем, что менее способные платформы ограничивают продвижение стандарта вперед, это проблема. Но это своего рода природа стандарта. Когда в стандарт вносятся дополнения, необходимо убедиться, что это, по крайней мере, каким-то образом возможно реализовать на платформах, реализующих стандарт. По крайней мере, среди основных игроков, и можно было бы сказать, что Xamarin подходит этой категории.

На мой взгляд, эта цифра в ее нынешнем виде - ложь. Xamarin утверждает, что поддерживает netstandard , но эта поддержка изобилует исключениями, которые для нас могут показаться разумными. Новичку это может быть не так просто понять.

image

@weshaggard

Продолжать публиковать System.Reflection.Emit как пакет netstandard в долгосрочной перспективе - не лучшее решение. Он снова делает стандартный "ложным" и должен быть доступен только для net / netcoreapp. Это горькая пилюля, поверьте мне, я знаю. У меня такая же проблема с LightInject.Interception, это прокси-библиотека, использующая System.Reflection.Emit . Но я бы предпочел нацелить netcoreapp на ложь потребителю, что эта библиотека может работать везде.

@seesharper

IMHO, выброс PlatformNotSupportedException - это просто еще одно проявление подмножества API, которое мы видели с PCL. Как и в случае с System.Reflection.Emit.LightWeight, мы действительно можем реализовать его, и нет причин для исключения PlatformNotSupportedException.

Они совсем не эквивалентны. Единственная причина, по которой .NET Standard полезен, заключается в его значительно большей поверхности API, которая позволяет нам создавать единую сборку для работы на нескольких платформах. PCL гораздо менее полезны, поскольку его сокращенное подмножество пересечений API вынуждает создавать несколько специфичных для платформы сборок для нетривиальных функций. Их возможности не эквивалентны, а решения, к которым они приводят, сильно различаются по сложности как для авторов библиотеки, так и для потребителей, с .NET Standard у нас есть единая сборка, которая работает на всех платформах, поскольку мы можем проверять во время выполнения, поддерживает ли платформа Reflection.Emit, если нет, мы возвращаемся к лямбда-выражениям и отражению. Если бы эти API не были доступны для стандартных библиотек .NET, у нас не было бы единой сборки, и нам пришлось бы вернуться к разработке и поддержке непереносимых сборок для конкретной платформы.

Продолжение публикации System.Reflection.Emit в качестве пакета netstandard - не лучшее решение в долгосрочной перспективе. Он снова делает стандартный "ложным" и должен быть доступен только для net / netcoreapp.

Принуждение к созданию и зависимости сборок для конкретных платформ - гораздо худший результат, особенно. с таким количеством транзитивных зависимостей, уже зависящих от него. Основное преимущество .NET Standard - это возможность создавать библиотеки и проекты для единственной полезной абстракции, если мы не можем использовать ее для доступа к основным функциям, доступным в .NET Core и .NET Framework, он не может решить ее основное использование. -case и также может не существовать, поскольку он просто добавляет больше абстракций / путаницы в экосистему .NET без каких-либо преимуществ по сравнению с PCL.

PCL уже пробовал связываться с абстракциями, которые раскрывают только пересечение функций API, доступных на каждой платформе, что, по сути, является тем, что вы просите вернуть, поскольку у вас будет доступ только к API, доступным на каждой платформе, и, по расширению, содержать только API. доступно на самой ограниченной платформе.

Наличие более широкой поверхности API в .NET Standard гораздо полезнее и дает авторам библиотек свободу выбора, как они хотят обрабатывать поддержку различных платформ. Если бы эти API-интерфейсы не были доступны, такой возможности не существовало бы. принудительно создавать сборки для конкретных платформ и заставлять все его зависимые библиотеки и проекты также поддерживать сборки для конкретных платформ, добавляя трение, фрагментацию, снижая переносимость и ограничивая поддержку только теми платформами, которые авторы выбирают поддерживать сборки для всех платформ, поддерживающих .NET Standard эта особенность.

Это не просто вопрос предпочтений: удаление основной поддержки API оказывает далеко идущее разрушительное влияние на доступные решения, заставляет ненужные сборки для конкретной платформы влиять на полезность библиотек, нарушая при этом все библиотеки .NET Standard и проекты, использующие их.

@weshaggard

У нас все еще нет отличного решения для их поддержки на netstandard2.0, но владельцы ( @AtsushiKan @joshfree) System.Relfection.Emit будут пытаться найти более долгосрочное решение.

Как насчет того, чтобы сказать iDiot и специалистам по контролю, которые навязывают AOT-только всем, кто использует их платформы, что им нужно сформировать и исправить свои плохие правила платформы? (Потому что, давайте будем честными, мы все знаем, что это действительно так: несколько очень конкретных плохих игроков в мобильном мире.)

@mythz , ты абсолютно прав.

@masonwheeler

Я полностью понимаю, что сокрытие пакета ref emit - это разочарование, учитывая вызванные им падения. Я также понимаю, что наша оптимизация для среды выполнения, которая вас не волнует, может расстроить, особенно когда это включает компромиссы, которые негативно влияют на сценарии, которые вас волнуют.

При этом я пометил ваш комментарий как "оскорбительный", поскольку он неконструктивен. Оскорбление людей не решит эти проблемы. Также учтите, что это не наша политика. Тот факт, что вы не можете генерировать и выполнять код во время выполнения на iOS, является политическим решением Apple. Кроме того, в некоторых случаях это ограничение не политическое, а технологическое.

Есть три варианта с отражением, излучением:

  1. Исправьте текущие пакеты и заставьте их работать поверх .NET Standard 2.0 . Проблема заключается в странных отношениях наследования между Type и TypeInfo в .NET Standard 1.x по сравнению с 2.0 и наличием закрытых конструкторов. Я могу вдаваться в подробности, но сделать пакет действительно собираемым без восстановления после взлома немного сложно, поэтому мы изначально решили скрыть пакеты.

  2. Добавить излучение отражения в .NET Standard vNext . Для поддержки сценариев только AOT это, вероятно, будет включать API-интерфейс возможностей, который позволяет потребителям проверять, поддерживается ли генерация кода или эффективна (то есть, используем ли мы реальное выполнение, а не интерпретацию).

  3. Отсутствие отражения излучения в .NET Standard и требование от авторов библиотеки многоцелевого использования . По сути, это был исходный путь, когда мы начали скрывать пакет.

Сейчас мы склоняемся к первому варианту, но второй вариант также рассматривается.

Я за 2. Достаточно повсеместно, чтобы быть там. В любом случае проверка возможностей нужна по другим причинам.

Я за 2. Достаточно повсеместно, чтобы быть там. В любом случае проверка возможностей нужна по другим причинам.

Я тоже, но это не поможет никому, кто в настоящее время полагается на .NET Standard 2.0, поскольку для этого требуется новая версия стандарта. Однако указанные API уже существуют.

Поэтому я думаю о минимальном исправлении, чтобы эти пакеты работали как есть, но также исправили .NET Standard 2.0 vNext.

@terrajobst Есть ли в варианте 1 что-то такое, что усложняет выполнение варианта 2? Мне кажется, что получение версии пакетов, нацеленных на netstandard2.0 вместо того, чтобы тянуть график пакетов netstandard1.1 , было бы хорошей краткосрочной целью. Тогда для vNext стандарта он может стать его частью, и вам больше не понадобятся пакеты.

Итак, если нет действительно веской причины не делать этого, я голосую как за 1, так и за 2.

@bording

Похоже, мы писали практически одновременно. Надеюсь, мой комментарий касается вашего вопроса :-)

Обратите внимание, что netstandard2.0 поддерживает статический метод System.Reflection.Assembly.Load(byte[] rawAssembly) , который загружает сборку из массива байтов двоичного изображения. Это означает, что можно реализовать не все, кроме большинства System.Reflection.Emit API, совместимые с чистым netstandard2.0 .

(Извините, я не знаю, сколько платформ поддерживают Assembly.Load без PNSE)

@GlassGrass, к каким фреймворкам, по вашему мнению, применима реализация netstandard2.0 ?

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

Фреймворки, которые имеют JIT (и поддерживают Assembly.Load), также могут напрямую поддерживать Ref.Emit и предоставлять свою реализацию Ref.Emit вместо версии netstandard2.0. Я знаю, что это так, по крайней мере, desktop / .netcore / .netnative. Первые два поддерживают ref.emit и предоставляют реализацию, более поздние не имеют, не имеют JIT и не поддерживают динамическую загрузку сборки.

Я действительно думаю, что было бы интересным проектом для кого-то поиграться в corefxlab, чтобы написать что-то поверх System.Reflection.Metadata которое выглядит как Ref.Emit (или лучше). Не уверен, что кто-нибудь уже на это смотрит. / cc @nguerrera @tmat

Я действительно думаю, что для кого-то было бы интересным проектом поиграть в corefxlab, чтобы написать что-нибудь поверх System.Reflection.Metadata, похожее на Ref.Emit (или лучше).

Это у меня на тарелке: (https://github.com/dotnet/corefx/issues/4491 и https://github.com/dotnet/corefx/issues/2800)

https://github.com/dotnet/corefx/issues/2800 будет первым, поскольку материал ref emit, вероятно, будет его расширением. Я начал создавать прототип 2800 на этой неделе и продолжу эту работу в ближайшие месяцы. Я не буду перемещать его в corefxlab, пока не продвинусь дальше. Рабочий процесс там на мой вкус слишком неэффективен.

@AtsushiKan : Рад видеть, что работа над этой проблемой все еще продолжается. Спасибо, что занялись этим.

Я уже упоминал следующее в другом месте: Одна вещь, которую System.Reflection.Metadata и Assembly.Load(byte[]) не могут сделать, - это пошаговое побудительное излучение. Вы не можете генерировать один тип, затем другой ... вы можете когда-либо испускать только полные сборки, что означает, что это не слишком полезно, например, для имитации библиотек, которые полагаются на генерацию динамического типа прокси.

Конечно, можно было когда-либо создавать только однотипные сборки, но это становится потенциально неэффективным и трудным, когда внутреннее устройство становится видимым для динамически генерируемых сборок через [assembly: InternalsVisibleTo] (еще одна вещь, которую часто требуют библиотеки для имитации / тестирования). Чтобы это работало, вы должны иметь возможность дать нескольким динамическим однотипным сборкам одно и то же удостоверение / строгое имя. (Среда выполнения может уже позволить это на практике, но я не могу найти документацию, официально подтверждающую это.)

@stakx Вы можете System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute чтобы она могла получить доступ к закрытым членам указанной сборки вместо использования IVT.

@tmat : Это интересно. Этот атрибут где-то официально задокументирован?

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

Будет ли это добавлено к .NET core 3.0 ?

Копия @steveharter @joshfree

@karelz https://github.com/dotnet/corefx/issues/30654 отслеживает работу для 3.0

@joshfree , это обман или это больше?

@karelz он затронул проблему с неправильным удалением пакета Ref.Emit из nuget, а затем этот пакет был повторно внесен в список @weshaggard. Я думаю, что теперь эту проблему можно закрыть, так как оставшаяся работа отслеживается с помощью dotnet / corefx # 30654.

ОК, закрываем :) ... оставшаяся работа отслеживается в dotnet / corefx # 30654, как упоминалось выше.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

matty-hall picture matty-hall  ·  3Комментарии

aggieben picture aggieben  ·  3Комментарии

GitAntoinee picture GitAntoinee  ·  3Комментарии

bencz picture bencz  ·  3Комментарии

noahfalk picture noahfalk  ·  3Комментарии