Runtime: ¿Debería haber una versión .Net Standard 2.0 de Reflection.Emit?

Creado en 27 abr. 2018  ·  58Comentarios  ·  Fuente: dotnet/runtime

System.Reflection.Emit no es parte de .Net Standard, pero hay paquetes que le permiten usarlo desde una biblioteca .Net Standard (específicamente, System.Reflection.Emit y System.Reflection.Emit.Lightweight ). Pero esos paquetes no tienen una versión .Net Standard 2.0, solo versiones .Net Standard 1.x.

Esto tiene algunas implicaciones:

  • Las bibliotecas .Net Standard 2.0 no pueden usar typeBuilder.CreateType() (aunque este código funciona tanto en .Net Framework 4.6.1 como en .Net Core 2.0) y tienen que usar typeBuilder.CreateTypeInfo().AsType() lugar. Es posible que también haya otras API como esta.
  • Las bibliotecas .Net Standard 2.0 que quieran utilizar Reflection.Emit todavía tienen que utilizar los paquetes System. * Estilo .Net Standard 1.x.

Estos problemas se resolverían si se agregara una versión .Net Standard 2.0 a los paquetes Reflection.Emit. ¿Es eso algo que valdría la pena hacer?

Aunque ambos son objeciones bastante pequeñas, no estoy seguro de cuánto valor agregaría esto.

area-System.Reflection.Emit question

Comentario más útil

Gracias a todos por la retroalimentación. En base a los abrumadores comentarios, hemos vuelto a poner en venta la última versión de los paquetes existentes:

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

Sin embargo, como se mencionó anteriormente en este hilo, estos paquetes afirman ser compatibles con netstandard1.1, pero eso es una mentira. Solo funcionarán en .NET Core y .NET Framework. Por lo tanto, si los consume de una biblioteca netstandard, espere que esa biblioteca falle si se ejecuta en cualquier otra implementación de .NET Standard.

Todavía no tenemos una gran solución para admitirlos en netstandard2.0, pero los propietarios ( @AtsushiKan @joshfree) de System.Relfection.Emit intentarán encontrar la solución a más largo plazo.

Todos 58 comentarios

@ericstj @weshaggard ¿sabes si es a propósito de esta manera o es un descuido?

Fue intencional. Para bibliotecas como esta que tienen soporte irregular y ninguna implementación portátil, dejamos de enviar paquetes. La expectativa es que apunte a un marco específico si lo necesita. Para algunos, hemos recuperado paquetes con minas terrestres (lanzando implementaciones en algunas plataformas). La gente podría proponer que lo agreguemos de nuevo, pero este en particular ha tenido un intenso debate en el pasado debido a la falta de soporte en todos los marcos .net basados ​​en AOT. / cc @terrajobst

@ericstj

La expectativa es que apunte a un marco específico si lo necesita.

¿Cómo se supone que voy a aprender sobre eso? Por lo que puedo decir, Reflection.Emit no es informado por platform-compat. Y cuando busqué en Google "reflejo emitido .Net Standard", el único resultado en la primera página que habla de si debe usarlo de esa manera es un tweet de julio de 2017 de @terrajobst sugiriendo que debe hacerlo (tal vez la situación cambió desde entonces ?).

Dejaré que

FWIW todo lo que esté disponible en un marco pero que no esté en netstandard o en una biblioteca / paquete con un activo netstandard significa que debe apuntar al marco para obtenerlo. Eso es todo lo que quise decir con mi comentario de expectativa.

@ericstj

cualquier cosa que esté disponible en un marco pero que no esté en netstandard o en una biblioteca / paquete con un activo netstandard significa que debe apuntar al marco para obtenerlo. Eso es todo lo que quise decir con mi comentario de expectativa.

Pero aquí existe el paquete (con activos .Net Standard 1.x). No creo que pueda dejar de actualizar un paquete y asumir que la gente ya no lo usará. Como mínimo, debe tener documentación que explique la situación.

El mayor problema con System.Reflection.Emit es que no tenemos una forma de proporcionar la biblioteca de una manera estándar debido a TypeInfo (consulte https://github.com/dotnet/corefx/issues/14334). El paquete existente apunta a netstandard1.1 pero es una mentira y solo funcionará en .NET Framework y .NET Core debido al estrecho acoplamiento que tenemos. Lo hackeamos para que funcione jugando trucos de InternalsVisibleTo para darle acceso a los constructores de TypeInfo, pero ese mismo truco es lo que hace que no funcione en una plataforma estándar .NET general. Decidimos no propagar más el error pirateando netstandard2.0 de la misma manera y, en cambio, dejamos de producir el paquete y lo hicimos específico de la plataforma.

Gracias por plantear el problema @svick y deberíamos usar este problema para documentar el problema con el paquete.

¿Qué pasa con la eliminación de los paquetes que ya no se actualizan en NuGet para que quede claro que no se recomiendan?

Esto es muy necesario. No poder crear y guardar ensamblados es actualmente mi principal bloqueador de dotnet / corefx # 1 para actualizar a .NET Core, y realmente me gustaría ver que la actualización de esta API fundamental sea una prioridad más alta que trabajar en nuevas funciones .

@masonwheeler solo para llamar, puede usar Reflection.Emit si está escribiendo una aplicación o biblioteca .NET Core, simplemente no puede usarla mientras escribe la biblioteca .NET Standard actualmente.

@weshaggard, ¿estás seguro? Acabo de revisar el repositorio y parece que no solo AssemblyBuilder.Save aún no se ha implementado, ¡ ni siquiera existe en Core! (Podría estar equivocado; estoy en mi teléfono y la interfaz móvil de GitHub no es la mejor, pero así es como se ve).

@masonwheeler tiene razón en que no Guarde en .NET Core que está siendo rastreado por otro problema https://github.com/dotnet/corefx/issues/4491.

¡Ahí está! Pensé que había visto ese problema antes, pero al buscar solo apareció este. :PAGS

Pero sí. Sin la capacidad de emitir sus resultados, realmente no puede decir que puede usar Reflection.Emit en Core. ☹️

@weshaggard antes de que el paquete System.Reflection.Emit.Lightweight no apareciera en la lista de nuget.org, era posible obtener el paquete Selenium.WebDriver en PowerShell 5 (para .Net Framework) y PowerShell Core 6 (para .Net Core 2.0) en Windows 10 usando el siguiente comando: Install-Package Selenium.WebDriver -Destination $ PSScriptRoot -Force -ForceBootstrap

Ahora, este comando no puede descargar todas las dependencias del paquete Selenium para ambas versiones de PowerShell. Falla porque el paquete System.Reflection.Emit.Lightweight.4.3.0 no está listado en nuget.org.
Error: paquete de instalación: no se pueden encontrar paquetes dependientes (System.Reflection.Emit.Lightweight)

¿Podría aconsejarme sobre cómo solucionar este problema?

@SergeyKhutornoy, ¿está llamando "Install-Package" en VS desde la consola del administrador de paquetes? Si es así, me instala correctamente el paquete. Si está llamando Install-Package desde Powershell, ese es un tipo diferente de administración de paquetes. De hecho, lo intenté localmente y obtengo un error diferente (Paquete de instalación: no se encontró ninguna coincidencia para los criterios de búsqueda especificados y el nombre del paquete 'Selenium.WebDriver'). No estoy familiarizado con ese sistema de administración de paquetes, así que estoy no estoy seguro de cómo solucionarlo. Una cosa que podría intentar es instalar explícitamente System.Reflection.Emit.Lightweight 4.3.0 primero y luego ver si funciona. Si eso no funciona, ¿hay alguna razón por la que no pueda usar VS o herramientas nuget para instalar el paquete?

No incluir este paquete en la lista es un error y no proporcionar una versión .NET Standard 2.0 es un error.

Estamos a punto de enviar una nueva versión importante de nuestro producto, NServiceBus, y nuestro objetivo es netstandard2.0 . También tenemos una dependencia de System.Reflection.Emit y System.Reflection.Emit.Lightweight. Originalmente tenía la intención de apuntar a .NET Framework y .NET Core por separado, pero una conversación en Twitter con @terrajobst combinada con el descubrimiento de que estos paquetes estaban disponibles me llevó a cambiar de planes y apuntar a netstandard2.0 lugar.

No me importa no poder guardar tanto ensamblados dinámicos, siempre puedo probar la lógica en un .NET Framework TFM, pero DynamicMethod es increíblemente útil y muy utilizado para generar procesadores de reflexión, delegados de convertidores, etc. Los paquetes. System.Reflection.Emit. * Tienen más de 20.000.000 descargas.

Traiga una forma de hacer referencia a DynamicMethod en las bibliotecas netstandard2.0.

¿Cómo usamos DynamicMethod en .NET Core ahora que no está listado como paquete?

@danielcrenna No necesita el paquete para usar DynamicMethod en .Net Core, ya que está integrado. Solo necesitaba el paquete para usarlo en .Net Standard.

Podría construir mi tiempo de ejecución (que ya está lanzado) en .netstandard 2.0 usando System.Reflection.Emit.Lightweight 4.3 como uso DynamicMethod. Ahora veo que el proceso de compilación extrae el paquete del caché sin conexión y no de nuget. ~ Si el caché fuera de línea está bloqueado, no puedo volver a compilar el código para .NETstandard. ~ (Alojar el caché hace que el proceso de compilación extraiga el paquete nuevamente, ya que el paquete todavía está allí, aunque no está listado, por lo que no es un éxito técnicamente, aunque semánticamente).

Mirando aquí: https://apisof.net/catalog/System.Reflection.Emit.DynamicMethod ¿cuál es la conclusión que tengo que sacar? ¿Que está en NS1.6? ¿O en alguna dimensión intermedia donde las 'extensiones de plataforma' son válidas?

Entonces, iow: como apunto .netstandard2.0 y uso DynamicMethod, puedo hacer una referencia a System.Reflection.Emit.Lightweight aunque no está listado y es compatible con ns1.6 (?), Pero esto se siente realmente mal: se siente como una responsabilidad, ya que ahora dependo de un paquete que no está listado (y luego tengo que esperar que los paquetes no listados se mantengan allí hasta el final de los tiempos). Lo triste es: no hay otra alternativa que depender de un paquete no listado que solo es posible porque uno conoce el nombre exacto.

// @terrajobst

Para agregar: EF Core 2.1 tiene una dependencia de Castle.Core (https://www.nuget.org/packages/Castle.Core/) para sus proxies, que depende de System.Reflection.Emit.

¿No es prudente que todos los involucrados tengan este paquete (y Emit.Lightweight) para simplemente volver a alistarse?

@FransBouma estrictamente hablando EF Core Proxies tiene la dependencia, no EF Core en sí. Pero es un desastre de todos modos.

De hecho, _FirebirdClient_ depende de _System.Reflection.Emit_. ¿Y qué hacer ahora, verdad?

Si bien es comprensible que las plataformas AOT completas no puedan permitir la generación de nuevos tipos en tiempo de ejecución, es más sorprendente que no podamos admitir System.Reflection.Emit.Lightweight en estas plataformas.
LambdaExpression.Compile() funciona en todas las plataformas incluso si se interpreta en AOT.

Soy el autor de la biblioteca LightInject DI y eso está usando Reflection.Emit y DynamicMethod para generar código en tiempo de ejecución. Todo esto estuvo bien hasta que estas otras plataformas comenzaron a surgir. SilverLight, WinRT, iOS y así sucesivamente. ¿Entonces lo que hay que hacer? Lo que hice fue "ajustar" los DynamicMethod para que los OpCodes se traduzcan en expresiones. Existe una especie de relación 1-1 entre los códigos de operación y las expresiones, por lo que no es tan difícil.

Eche un vistazo aquí para ver la implementación.
https://github.com/seesharper/LightInject/blob/a01be40607761d9b446dc4acad37d7f717742975/src/LightInject/LightInject.cs#L4483

Tenga en cuenta que no implemento todos los códigos de operación. Solo los que necesito.

Mi punto es que debería ser posible hacer esto para todos los OpCodes y luego habilitar MUCHAS bibliotecas para seguir apuntándose a netstandard2.0. La mayoría de las bibliotecas que utilizan Reflection.Emit no generan nuevos tipos. Simplemente generan código a través del DynamicMethod

También tenga en cuenta que DynamicProxy, Moq y otras bibliotecas que generan tipos en tiempo de ejecución no pueden apuntar a netstandard2.0 . Deben ser netcoreapp ya que básicamente dependen de AssemblyBuilder con amigos
Entonces, la conclusión es que el paquete System.Reflection.Emit.Lightweight nunca se puede eliminar de NuGet por completo como netstandard2.0 . Esa sería la historia de LeftPad de nuevo

Mis dos centavos

¿Hay una lista en alguna de las MDTs que apoyan System.Reflection.Emit ? Acabo de agregar net45 y netcoreapp2.0 TFM explícitos a mi proyecto, pero estoy seguro de que me faltan algunos.

@jbogard Todos los TFM de marco completo deberían ser buenos además de los TFM de netcoreapp. ¿Está esto en AutoMapper?

Esta parece una decisión mal pensada y comunicada con consecuencias de gran alcance que parece haberse tomado con muy poca participación de la comunidad a la que afecta, lo que sorprende dado que los paquetes tienen 22 millones de descargas. ¿No justifica eso algún tipo de análisis sobre el impacto potencial en todos los que actualmente dependen de él?

ServiceStack hace referencia a los paquetes Reflection.Emit ahora eliminados en ServiceStack.Text, que es el paquete de dependencia base que se usa de manera efectiva en netstandard2.0 y net45 , forzando la orientación a la plataforma .netcore rompería cada dependencia y cada proyecto netstandard2.0 que la use, es decir, el marco de destino preferido para crear plataformas cruzadas compilaciones que admiten tanto .NET Framework como .NET Core.

Entonces, ¿cuál es la recomendación ahora para los paquetes que usan Reflection.Emit? ¿Dejar de publicar compilaciones .NET Standard 2.0 y decirles a todos que ya no pueden crear compilaciones .NET Standard 2.0 para sus bibliotecas y proyectos?

La solución anterior para usar las API estándar de .NET que no implementan la API era lanzar excepciones de tiempo PlatformNotSupportedException ejecución

@seesharper sí, los agregué, pero eso podría dejar fuera a otros. Los documentos de la API enumeran más, pero ¿qué otros podrían faltar? ¿Es esa una lista completa de posibles TFM que admiten la API? ¿Qué tal, digamos, xamarinxboxone ?

He refactorizado mi código DynamicMethod / ILGenerator que usé para emitir métodos setter para propiedades en tiempo de ejecución con una solución Lambda.Compile (), por lo que la dependencia de Reflection.Emit ya no existe, sin embargo, tuve que pasar 3-4 horas en él que me hubiera gustado gastar en otras cosas. Pero, por desgracia, así es la vida cuando las cosas 'se mueven rápido y se rompen a menudo', supongo.

De todos modos, lo que encuentro un poco perturbador es el silencio ensordecedor del personal de Microsoft en este hilo durante las últimas semanas. Se siente como debatir cosas en una sala cuando las personas que realmente pueden cambiar las cosas no están allí.

Estoy totalmente de acuerdo con @mythz y otros aquí, está mal comunicado y con 22 millones de descargas fue una decisión tonta con consecuencias de gran alcance.

@mythz No sé cómo lo estás usando, pero para mis cosas, tuve que volver a #if feature flags para eliminar la funcionalidad en plataformas que no admiten tipos de construcción sobre la marcha (en mi biblioteca, siendo capaz de mapear a una interfaz y creo un proxy sobre la marcha).

@jbogard Usamos una bandera booleana Env.SupportsEmit para determinar en tiempo de ejecución si la plataforma es compatible con Reflection.Emit, si lo hace lo usamos, de lo contrario recurrimos a Expresiones compiladas. En esa nota, sería útil si hubiera una bandera Platform.SupportsEmit que todos pudieran usar para verificar si la plataforma en ejecución es compatible con Reflection.Emit.

La directiva #if requeriría la creación de múltiples compilaciones de plataforma que serían la causa del cambio radical para todos los paquetes y proyectos dependientes que apuntan a .netstandard2.0 , ya que también requieren .netstandard2.0 dependencias.

Solo para una discusión más detallada, me gustaría asegurarme de que todos estamos en la misma página cuando se trata de la diferencia entre System.Reflection.Emit y System.Reflection.Emit.Lightweight .

En realidad, este problema debería haberse dividido en dos temas separados. 😄

  • ¿Debería haber una versión .Net Standard 2.0 de Reflection.Emit?
  • ¿Debería haber una versión .Net Standard 2.0 de System.Reflection.Emit.LightWeight?

System.Reflection.Emit

Este paquete contiene AssemblyBuilder y las clases relacionadas que necesitamos para generar ensamblados / tipos en tiempo de ejecución.
El problema con este paquete es que nunca debería haberse puesto en NuGet como un paquete netstandard ya que la generación de nuevos tipos en tiempo de ejecución no se puede admitir en plataformas AOT completas.
Supongo que Microsoft agregó esto como un paquete netstandard para facilitar la migración del marco completo a las bibliotecas .Net Core y netstandard . En retrospectiva, no es realmente la mejor idea.
El enfoque de "cebo y cambio" (entendido por como 5 personas en todo el mundo) tampoco es una gran solución.

System.Reflection.Emit.LightWeight

Este paquete contiene DynamicMethod que hace posible compilar código dinámicamente SIN crear nuevos tipos. El "método dinámico" es básicamente un método estático para el que podemos crear un delegado que se utiliza para invocar el método.
LambdaExpression.Compile es básicamente el mismo ting y si miramos la implementación en el marco completo veremos que en realidad usa DynamicMethod debajo de las cubiertas.
La cuestión es que LambdaExpression.Compile() funciona en todas las plataformas que utilizan interpretación en AOT. Debido a esto, no hay ninguna razón por la que no podamos crear un paquete System.Reflection.Emit.LightWeight que sea netstandard usando la técnica que describí anteriormente en este hilo.

Supongo que la razón para dar marcha atrás en esto ahora es asegurar que el estándar realmente dé algún significado en el futuro. El problema, tal como yo lo veo, es que podríamos ver paquetes de biblioteca dirigidos a netcoreapp lugar de netstandard y eso sería realmente malo cuando se trata de desarrollar todo el concepto de netstandard .

Mi sugerencia es hacer un esfuerzo por publicar System.Reflection.Emit.LightWeight como un verdadero paquete netstandard y continuar presionando por netcoreapp cuando se trata de System.Reflection.Emit .

@seesharper Hasta donde yo sé, Reflection.Emit (incluido Reflection.Emit.Lightweight) se usa principalmente para el rendimiento. Pero si implementó Reflection.Emit.Lightweight utilizando un intérprete de IL, su rendimiento probablemente sería bastante malo. Así que no estoy convencido de que el esfuerzo de admitir el modo de interpretación de IL en Reflection.Emit.Lightweight estaría justificado.

También es extraño que System.Reflection.Emit.ILGenerator todavía esté en la lista (https://www.nuget.org/packages/System.Reflection.Emit.ILGeneration), ya que es un paquete netstandard1.6, sin embargo ILGenerator no tiene implementación de UWP (https://apisof.net/catalog/System.Reflection.Emit.ILGenerator).

Iow: un poco desordenado, ¿no?

@seesharper Buena sugerencia.

@svick No creo que sea una justificación suficiente para cortarlo. Los lenguajes específicos de dominio necesitan la capacidad de construir código en tiempo de ejecución. Los DSL aparecen con bastante frecuencia en proyectos grandes ( la décima regla de Greenspun ), y es mejor si cada escritor no tiene que inventar y escribir su propio intérprete para ello (usando la reflexión regular y Invoke ). Si es un componente estándar, se mitigarían al menos las partes de la regla "especificadas informalmente y con errores". En cuanto al rendimiento de una implementación de orientación AOT, no tiene que ser un intérprete de IL. Incluso en plataformas que no permiten que un proceso cree páginas de memoria ejecutables, se pueden compilar métodos dinámicos en código enhebrado como lo hacen muchas implementaciones de FORTH, y para pequeños métodos dinámicos donde el "cuerpo del método" encaja en un par de líneas de caché, el La sobrecarga del tiempo de ejecución debe ser bastante baja.

El problema con este paquete es que nunca debería haberse colocado en NuGet como un paquete netstandard, ya que la generación de nuevos tipos en tiempo de ejecución no se puede admitir en plataformas AOT completas.

Discrepar. Las principales plataformas .NET Core y .NET Framework lo admiten, solo porque los entornos AOT no deberían impedir que admita las principales plataformas .NET dirigidas a netstandard2.0 .

¿Se ha convertido ahora en la estrategia de .NET Standard en el futuro? ¿Se eliminarán ahora las API que no son compatibles con los entornos AOT? Entonces, no habrá más excepciones de PlatformNotSupportedException , ¿las API se eliminarán en lugar de regresar a un subconjunto de PCL? ¿O vamos a ser inconsistentes y reduciremos selectivamente la superficie de la API para algunas funciones pero continuaremos agregando otras?

Apoyar la intersección de las API de denominador común más bajo fue lo que hizo PCL y resultó en una experiencia de desarrollo horrible que obligó a la técnica de cebo y cambio de PCL y a delegar en múltiples implementaciones específicas de la plataforma, que es toda la inversión que desperdiciamos cuando nos mudamos. NET estándar.

La mejor solución fue la existente (especialmente porque eliminarlo ahora es un cambio disruptivo y rompedor en sus deps transitivos) que nos permite usar Reflection.Emit en todas las plataformas que lo admitieron mientras necesitamos implementar un respaldo para las que no lo hacen. . Eliminar la capacidad de usar Reflection.Emit en .NET Standard significa que las bibliotecas que lo usan ya no pueden apuntar a .NET Standard. ¿Cuál es el punto si no podemos usar características que comparten .NET Core y .NET Framework en una abstracción independiente de la plataforma? Solo estaría agregando abstracciones / confusión / complejidad innecesarias al ecosistema .NET sin beneficios.

Gracias a todos por la retroalimentación. En base a los abrumadores comentarios, hemos vuelto a poner en venta la última versión de los paquetes existentes:

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

Sin embargo, como se mencionó anteriormente en este hilo, estos paquetes afirman ser compatibles con netstandard1.1, pero eso es una mentira. Solo funcionarán en .NET Core y .NET Framework. Por lo tanto, si los consume de una biblioteca netstandard, espere que esa biblioteca falle si se ejecuta en cualquier otra implementación de .NET Standard.

Todavía no tenemos una gran solución para admitirlos en netstandard2.0, pero los propietarios ( @AtsushiKan @joshfree) de System.Relfection.Emit intentarán encontrar la solución a más largo plazo.

@svick

Hasta donde yo sé, Reflection.Emit (incluido Reflection.Emit.Lightweight) se utiliza principalmente para el rendimiento. Pero si implementó Reflection.Emit.Lightweight utilizando un intérprete de IL, su rendimiento probablemente sería bastante malo. Así que no estoy convencido de que el esfuerzo de admitir el modo de interpretación de IL en Reflection.Emit.Lightweight estaría justificado.

Tengo entendido que LambaExpression.Compile() y su ejecución se interpretan en plataformas AOT y, por lo tanto, no debería ser peor hacerlo por System.Reflection.Emit.LightWeight .
Hay muchas bibliotecas que usan este paquete y tener un paquete netstandard2.0 "verdadero" permitiría repentinamente que esos paquetes se ejecuten en su iPhone sin forzar a los desarrolladores de estos paquetes a reescribir su código para que coincida con las diferentes plataformas. El rendimiento se degradaría, pero funcionaría tal como lo hace hoy con LambdaExpression.Compile()

@mythz

¿Se ha convertido ahora en la estrategia de .NET Standard en el futuro? ¿Se eliminarán ahora las API que no son compatibles con los entornos AOT? Entonces, ¿no habrá más excepciones de PlatformNotSupportedException, las API serán retiradas en lugar de retroceder hacia un subconjunto de PCL? ¿O vamos a ser inconsistentes y reduciremos selectivamente la superficie de la API para algunas funciones pero continuaremos agregando otras?

En mi humilde opinión, lanzar PlatformNotSupportedException es solo otra manifestación del subconjunto de API que vimos con PCL. Como es el caso de System.Reflection.Emit.LightWeight , podemos implementarlo y no hay razón para lanzar un PlatformNotSupportedException . Sin embargo, estoy de acuerdo en que es problemático que las plataformas menos capaces impidan que el estándar avance. Pero esa es la naturaleza de tener un estándar. Cuando se realizan adiciones al estándar, debe asegurarse que sea al menos de alguna manera posible implementarlo por las plataformas que implementan el estándar. Al menos entre los principales actores y diría que Xamarin encaja en esa categoría.

Esta cifra tal como está hoy es una especie de mentira como yo la veo. Xamarin afirma admitir netstandard , pero ese soporte está plagado de excepciones que para nosotros pueden parecer razonables. Para el novato, puede que no sea tan fácil de entender.

image

@weshaggard

Continuar publicando System.Reflection.Emit como un paquete netstandard no es una buena solución a largo plazo. Hace que el estándar sea "falso" nuevamente y solo debería estar disponible para net / netcoreapp. Es una píldora amarga de tragar, créanme que lo sé. Tengo exactamente el mismo problema con 'LightInject.Interception' que es una biblioteca proxy que usa System.Reflection.Emit . Pero prefiero apuntar a netcoreapp en lugar de mentirle al consumidor que esta biblioteca se puede ejecutar en todas partes.

@seesharper

En mi humilde opinión, lanzar PlatformNotSupportedException es solo otra manifestación del subconjunto de API que vimos con PCL. Como es el caso de System.Reflection.Emit.LightWeight, en realidad podemos implementarlo y no hay razón para lanzar una PlatformNotSupportedException.

No son equivalentes en absoluto. La única razón por la que .NET Standard es útil se debe a su superficie de API mucho mayor que nos permite crear una única compilación para ejecutar en múltiples plataformas. Las PCL son mucho menos útiles ya que su subconjunto de intersección de API reducido forzó la creación de compilaciones específicas de múltiples plataformas para una funcionalidad no trivial. Sus capacidades no son equivalentes y las soluciones a las que conducen son muy diferentes en complejidad tanto para los autores de bibliotecas como para los consumidores, con .NET Standard tenemos una única compilación que se ejecuta en todas las plataformas, ya que podemos verificar en tiempo de ejecución si la plataforma es compatible Reflection.Emit, si no es así, recurrimos a Lambda Expressions y Reflection. Si estas API no estuvieran disponibles para las bibliotecas .NET Standard, no podríamos tener una sola compilación y tendríamos que volver a desarrollar y mantener compilaciones específicas de plataforma no portátiles.

Continuar publicando System.Reflection.Emit como un paquete netstandard no es una buena solución a largo plazo. Hace que el estándar sea "falso" nuevamente y solo debería estar disponible para net / netcoreapp.

Forzar la creación y dependencia de compilaciones específicas de la plataforma es un resultado mucho peor, especialmente. con tantas dependencias transitivas que ya dependen de él. El beneficio principal de .NET Standard es poder crear bibliotecas y proyectos para apuntar a una única abstracción útil, si no podemos usarlo para acceder a las funciones principales disponibles en .NET Core y .NET Framework, no puede resolver su uso principal -case y es posible que no exista ya que solo agrega más abstracciones / confusión al ecosistema .NET sin ningún beneficio sobre las PCL.

PCL ya intentó vincularse a abstracciones que solo exponen la intersección de las funciones de API disponibles en cada plataforma, que es efectivamente a lo que está pidiendo volver, ya que solo tendrá acceso a las API disponibles en cada plataforma y, por extensión, solo contienen API disponible en la plataforma más restringida.

Tener una API Surface más amplia en .NET Standard es mucho más útil y les da a los autores de bibliotecas la libertad de poder elegir cómo quieren manejar el soporte para diferentes plataformas; si estas API no estuvieran disponibles, esa opción no existiría. forzar las compilaciones específicas de la plataforma y obligar a todas sus bibliotecas y proyectos dependientes a mantener también compilaciones específicas de la plataforma, lo que agrega fricción, fragmentación, reduce la portabilidad y limita el soporte solo a las plataformas que los autores eligen mantener compilaciones frente a todas las plataformas que admiten .NET Standard que admiten esa característica.

No es solo una cuestión de preferencia, eliminar el soporte de API convencional tiene un impacto disruptivo de gran alcance en las soluciones disponibles, obliga a compilaciones específicas de la plataforma innecesarias que afectan la utilidad de las bibliotecas y rompe todas las bibliotecas y proyectos de .NET Standard que las usan.

@weshaggard

Todavía no tenemos una gran solución para admitirlos en netstandard2.0, pero los propietarios ( @AtsushiKan @joshfree) de System.Relfection.Emit intentarán encontrar la solución a más largo plazo.

¿Qué tal si les dices a los iDiots y a los fanáticos del control que fuerzan el AOT solo a todos los que usan sus plataformas que necesitan para dar forma y corregir sus malas reglas de plataforma? (Porque seamos honestos, todos sabemos que de eso se trata realmente: algunos malos actores muy específicos en el mundo móvil).

@mythz , tienes toda la razón.

@masonwheeler

Entiendo completamente que ocultar el paquete ref emit es frustrante, considerando la caída que causó. También entiendo que la optimización de los entornos de ejecución que a usted no le importan puede resultar molesta, especialmente cuando esto incluye compensaciones que afectan los escenarios que le interesan negativamente.

Dicho esto, he marcado su comentario como "abusivo", ya que no es constructivo. Insultar a la gente no va a solucionar estos problemas. También considere que esta no es una política que controlemos. El hecho de que no pueda generar y ejecutar código en tiempo de ejecución en iOS es una decisión política de Apple. Además, en algunos casos no es una restricción política sino tecnológica.

Hay tres opciones con emisión de reflexión:

  1. Arregle los paquetes actuales y haga que funcionen sobre .NET Standard 2.0 . El problema es una extraña relación de herencia entre Type y TypeInfo en .NET Standard 1.x en comparación con 2.0 y tener constructores no públicos. Puedo entrar en más detalles, pero para que el paquete sea realmente compilable sin restaurarlo a los hacks es un poco complicado, por lo que originalmente decidimos ocultar los paquetes.

  2. Agregue la emisión de reflexión a .NET Standard vNext . Para admitir escenarios de solo AOT, esto probablemente incluiría una API de capacidad que permita a los consumidores verificar si la generación de código es compatible o eficiente (es decir, si usamos ejecución real en lugar de interpretación).

  3. No exponer la emisión de reflexión a .NET Standard y requiere que los autores de la biblioteca tengan varios destinos . Esta era básicamente la ruta original cuando comenzamos a ocultar el paquete.

En este momento, nos inclinamos hacia la primera opción, pero la segunda opción también está sobre la mesa.

Estoy a favor de 2. Es lo suficientemente omnipresente como para que esté allí. Necesitamos la verificación de capacidad de todos modos por otras razones.

Estoy a favor de 2. Es lo suficientemente omnipresente como para que esté allí. Necesitamos la verificación de capacidad de todos modos por otras razones.

Yo también, pero no ayudará a nadie que confíe actualmente en .NET Standard 2.0, ya que esto requiere una nueva versión del estándar. Sin embargo, las API en cuestión ya existen.

Así que estoy pensando en una solución mínima para que estos paquetes funcionen como están, pero también para corregir .NET Standard 2.0 vNext.

@terrajobst ¿Hay algo en la opción 1 que haga que la opción 2 sea más difícil de hacer? Me parece que obtener una versión de los paquetes que tengan como objetivo netstandard2.0 lugar de tener que extraer el gráfico del paquete netstandard1.1 sería un buen objetivo a corto plazo. Luego, para vNext del estándar, podría convertirse en parte de él y ya no necesitaría los paquetes.

Entonces, a menos que haya una buena razón para no hacerlo, voto por el 1 y el 2.

@bording

Parece que publicamos prácticamente al mismo tiempo. Espero que mi comentario responda a tu pregunta :-)

Tenga en cuenta que netstandard2.0 admite el método estático System.Reflection.Assembly.Load(byte[] rawAssembly) , que carga un ensamblado desde una matriz de bytes de imagen binaria. Esto significa que es posible implementar no todos, pero la mayoría de System.Reflection.Emit API compatibles con netstandard2.0 puros.

(Lo siento, no sé cuántas plataformas admiten Assembly.Load sin PNSE)

@GlassGrass ¿a qué marcos imagina que se aplicaría una implementación netstandard2.0 ?

Ciertamente puedo imaginar alguna implementación que escribiría el IL y produciría un ensamblado como un ILASM impulsado por API, pero no veo marcos actuales donde me gustaría usar eso.

Los marcos que tienen un JIT (y admiten Assembly.Load) también podrían admitir Ref.Emit directamente y proporcionar su implementación Ref.Emit en lugar de una versión netstandard2.0. Sé que este es el caso al menos de escritorio / .netcore / .netnative. Los dos primeros admiten la emisión de referencias y proporcionan una implementación, el segundo no, ni tiene un JIT ni admite la carga dinámica de ensamblajes.

Creo que sería un proyecto interesante que alguien jugara en corefxlab y escribiera algo sobre System.Reflection.Metadata que se parezca a Ref.Emit (o mejor). No estoy seguro de si alguien ya está mirando eso. / cc @nguerrera @tmat

Creo que sería un proyecto interesante que alguien jugara en corefxlab para escribir algo sobre System.Reflection.Metadata que se parezca a Ref.Emit (o mejor).

Eso está en mi plato: (https://github.com/dotnet/corefx/issues/4491 y https://github.com/dotnet/corefx/issues/2800)

https://github.com/dotnet/corefx/issues/2800 vendrá primero, ya que es probable que el material de emisión de referencia sea una extensión de él. Comencé a hacer prototipos 2800 esta semana y continuaré con ese trabajo en los próximos meses. No lo moveré a corefxlab hasta que esté mucho más avanzado. El flujo de trabajo es demasiado ineficiente para mi gusto.

@AtsushiKan : Me alegra ver que todavía hay trabajo en curso sobre este tema. Gracias por abordar esto.

Anteriormente mencioné lo siguiente en otro lugar: Una cosa que System.Reflection.Metadata y Assembly.Load(byte[]) no pueden hacer es la emisión incremental tipo por tipo. No puede emitir un tipo, luego otro ... solo puede emitir ensamblajes completos, lo que significa que esto no es demasiado útil para, por ejemplo, burlarse de bibliotecas que dependen de la generación dinámica de tipos de proxy.

Por supuesto, uno solo podría producir ensamblajes de un solo tipo, pero esto se vuelve potencialmente ineficiente y difícil cuando se hacen visibles los componentes internos para los ensamblajes generados dinámicamente a través de [assembly: InternalsVisibleTo] (otra cosa que las bibliotecas de prueba / burla a menudo requieren). Tendría que poder dar a varios ensamblados dinámicos de tipo único la misma identidad / nombre seguro para que esto funcione. (Es posible que el tiempo de ejecución ya lo permita en la práctica, pero no puedo encontrar documentación que lo confirme oficialmente).

@stakx Puede emitir System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute al ensamblado dinámico para permitirle acceder a miembros no públicos del ensamblado especificado, en lugar de utilizar IVT.

@tmat : Esto es interesante. ¿Este atributo está oficialmente documentado en alguna parte?

Es una pena que este atributo especial no esté documentado oficialmente, de alguna manera hace que sea un poco arriesgado usarlo fuera del tiempo de ejecución.

¿Se agregaría esto a .NET core 3.0 ?

cc @steveharter @joshfree

@karelz https://github.com/dotnet/corefx/issues/30654 rastrea el trabajo para 3.0

@joshfree ¿este es un engaño o cubre más?

@karelz cubrió el problema con el paquete Ref.Emit que se eliminó incorrectamente de nuget y luego @weshaggard volvió a enumerar el paquete. Creo que este problema ahora se puede cerrar ya que el trabajo restante se rastrea con dotnet / corefx # 30654.

OK, cerrando entonces :) ... el trabajo restante se rastrea en dotnet / corefx # 30654 como se mencionó anteriormente.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

jkotas picture jkotas  ·  3Comentarios

btecu picture btecu  ·  3Comentarios

chunseoklee picture chunseoklee  ·  3Comentarios

noahfalk picture noahfalk  ·  3Comentarios

GitAntoinee picture GitAntoinee  ·  3Comentarios