.net - newtonsoft - la definición del manifiesto del ensamblado no coincide con la referencia al ensamblado
No se puede resolver el problema de referencia de ensamblado sin frameworkAssemblies (3)
Estoy tratando de validar que Protocol Buffers funcionará con los nuevos tiempos de ejecución portátiles del equipo ASP.NET y, de manera ideal, la mayoría de los otros entornos modernos. La compilación 3.0.0-alpha4 se creó hace un tiempo usando profile259, por lo que esperaría que se requirieran algunos cambios en algunos casos, pero pensé en intentarlo. Soy consciente de la publicación de Oren Novotny sobre apuntar a .NET Core , y esperaba tener que hacer algunos cambios en el archivo Google.Protobuf nuspec , pero el error con el que me estoy encontrando me ha dejado perplejo.
Versión DNX: 1.0.0-rc1-update1
El escenario que estoy intentando probar actualmente es una aplicación de consola dirigida a dnx451. Tengo una aplicación de muestra muy simple:
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);
}
}
... y un pequeño
project.json
:
{
"compilationOptions": { "emitEntryPoint": true },
"dependencies": { "Google.Protobuf": "3.0.0-alpha4" },
"frameworks": {
"dnx451": { }
}
}
Tenga en cuenta que ni siquiera estoy usando
dnxcore*
aquí; irónicamente, conseguí
que
funcione sin problemas.
dnu restore
funciona bien;
dnx run
falla con:
Error: c: / Users / Jon / Test / Projects / protobuf-coreclr / src / ProtobufTest / Program.cs (9,9): DNX, Versión = v4.5.1 error CS0012: El tipo ''Objeto'' se define en un ensamblaje eso no está referenciado. Debe agregar una referencia al ensamblado ''System.Runtime, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a''.
Los siguientes cambios dan como resultado el mismo error:
-
Agregar explícitamente una dependencia a
"System.Runtime": "4.0.0"
en la sección dedependencies
para el marco -
Agregar explícitamente una dependencia a
"System.Runtime": "4.0.0-beta-23109"
en la sección dedependencies
para el marco, y también para4.0.10-beta-*
,4.0.20-beta-*
y4.0.21-beta*
. -
Añadiendo dependencias a
System.Runtime
dentro del paquete NuGet (localmente) y reconstruyendo contra eso:project.lock.json
se actualizó para incluir System.Runtime v4.0.0, pero se produjo el mismo error -
Lo mismo incluye un directorio
lib/dotnet
en el paquete, así como las dependencias
Pasos que funcionaron (de forma independiente y sin entradas de
dependencies
), pero me confunden:
-
Cambiar la llamada
Console.WriteLine
a soloConsole.WriteLine("foo")
(pero no hay otros cambios) -
Cambiar el tipo de la variable de
duration
aobject
lugar deDuration
-
Eliminando por completo toda sugerencia de Buffers de protocolo, y en su lugar usando
TimeSpan
o similar -
Agregando lo siguiente a project.json en la sección
dnx451
:"frameworkAssemblies": { "System.Runtime": "" }
En última instancia, no quiero que los usuarios tengan que hacer esto, al menos, no por el uso de Protocol Buffers. Supongo que esto tiene algo que ver con la forma en que estamos creando Protocol Buffers, pero como no entiendo la causa correctamente, es difícil de solucionar.
Espero que si pudiera encontrar una manera de hacer que funcione una entrada de
dependencies
, podría agregar esa dependencia en Protocol Buffers, lo cual estaría bien, pero como tener una dependencia en System.Runtime v4.0.0 en el project.lock el archivo no parece ayudar, debo estar perdiendo algo :(
Entonces, si entrecierra los ojos y mira el project.json, es básicamente un nuspec con un poco de goop para describir qué opciones de compilación y fuentes se necesitan para construir el proyecto.
Nuspecs hoy tiene 2 secciones,
frameworkAssemblies
para cosas "integradas" y
dependencies
para otras dependencias nuget.
Tiene el mismo significado aquí.
Cuando usa algo de "el marco", debe especificarse en
frameworkAssemblies
en lugar de ser una dependencia del paquete nuget.
Ahora en detalles:
Cuando utiliza una biblioteca basada en PCL o .NET Core en .NET Framework, las referencias son a ensamblajes de referencia (a veces llamados ensamblajes contractuales).
Algunos ejemplos de estos son cosas como
System.Runtime
,
System.Threading
, etc. Al usar proyectos basados en MSBUILD, se ejecuta una tarea que básicamente agrega automáticamente
todas
las referencias de
System.*
compilador de C # para evitar este desastre.
Estos ensamblados se denominan fachadas en .NET Framework.
La parte desafortunada es que los agrega a
TODOS
, incluso si no se usan.
Una dependencia de
System.Runtime
es el desencadenante de este comportamiento (cuando se ejecuta en archivos csproj basados en .NET Framework).
La razón por la que agregar una referencia al mismo paquete no funciona es porque la carpeta .NET Framework (net4 *) para esos ensambles de contratos (como System.Runtime), no tiene ningún dlls en ellos.
Si observa esas carpetas, verá un archivo
_._
vacío.
El razonamiento para esto es porque cuando declaras un paquete nuget con una referencia
frameworkAssembly
a
System.Runtime
, los sistemas de proyecto msbuild no lo instalan (error muy complicado y problema de diseño).
Eso probablemente hizo las cosas más confusas ...
He aceptado
la respuesta de David Fowler
como la razón
por la que
sucedió todo esto.
Ahora, en términos de lo que debo
hacer al
respecto, parece que solo necesito agregar un elemento
frameworkAssemblies
en el archivo
Google.Protobuf
para
Google.Protobuf
.
<package>
<metadata>
...
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Runtime" targetFramework="net45" />
</frameworkAssemblies>
</metadata>
...
</package>
Esa referencia de
frameworkAssembly
luego termina en
project.lock.json
en el proyecto del cliente, y todo está bien.
Sin embargo, a juzgar por el otro comentario de David ("Vamos a ver cómo solucionar esto") es posible que no necesite hacer nada de todos modos ...
Me parece que su problema existe solo porque ha elegido la aplicación Consola en lugar de "Aplicación web ASP.NET" / "Plantillas ASP.NET 5" / "Vacío".
Hice un uso simple de la prueba Plantilla vacía, agregué
"Google.Protobuf": "3.0.0-alpha4"
de NuGet y finalmente modifiqué
Startup.cs
para que use
Google.Protobuf.WellKnownTypes
:
-
agregado
using Google.Protobuf.WellKnownTypes;
-
var duration = new Duration { Seconds = 100, Nanos = 5555 };
agregadavar duration = new Duration { Seconds = 100, Nanos = 5555 };
dentro deConfigure
-
modificado
await context.Response.WriteAsync("Hallo World!");
await context.Response.WriteAsync(duration.ToString());
El código final de
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);
}
}
La aplicación ASP.NET 5 resultante se mostró con éxito
100.5555s
en el navegador web.
Puede descargar el proyecto de demostración desde here .
ACTUALIZADO:
analicé el problema con la aplicación DNX de consola pura, que usa el código y pude encontrar la razón del
problema en la
duration.ToString()
Método
ToString
duration.ToString()
, que funciona en el entorno ASP.NET, pero no en la aplicación de consola pura.
La razón del problema es interesante y estoy tratando de investigar, pero quería compartir mis resultados actuales con otros
Podría hacer funcionar el siguiente código:
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);
}
}
}
Uno puede descargar el proyecto de trabajo desde here .
Comenté adicionalmente la línea
//[assembly: Guid("b31eb124-49f7-40bd-b39f-38db8f45def3")]
en
AssemblyInfo.cs
para no tener referencias innecesarias a
"Microsoft.CSharp"
, que tienen muchas otras referencias.
El
project.json
contiene en el proyecto de demostración:
{
...
"dependencies": {
"Google.Protobuf": "3.0.0-alpha4"
},
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
"System.Console": "4.0.0-beta-23516"
}
}
}
}
Por cierto, incluyendo
"System.Console": "4.0.0-beta-23516"
se requiere
"System.Console": "4.0.0-beta-23516"
en
"dnxcore50"
parte de
"frameworks"
porque el espacio de nombres de la
Console
(para
Console.WriteLine
) existe en
mscorlib
de
DNX 4.5.1
.
Si se trata de agregar
"System.Console": "4.0.0-beta-23516"
en el nivel de dependencias
comunes,
se obtiene el error que comienza con el texto
Error CS0433 El tipo ''Console'' existe en ''System.Console, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a'' y ''mscorlib, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089'' ConsoleApp3.DNX 4.5.1
ACTUALIZADO 2: se puede reemplazar la línea
Console.WriteLine("{0}.{1:D4}s", duration.Seconds, duration.Nanos);
a
Console.WriteLine((object)duration);
para que funcione
Solo el uso de
Console.WriteLine(duration);
o
var str = duration.ToString();
produce el error, que usted describió.
ACTUALIZADO 3:
Verifiqué que la
duration.ToString()
del código.
duration.ToString()
llama a
las líneas
que usan
las líneas
para formatear.
Parece que la
duration.ToString()
del código.
duration.ToString()
hace realmente lo mismo que
((object)duration).ToString()
para los tipos
WellKnownTypes
(como
Duration
).
El último comentario que me parece importante. El problema descrito solo existe para dnx451 (o dnx452 o dnx46). Si uno quitara las lineas
"dnx451": { },
desde
"frameworks"
parte de
project.json
entonces el programa se compilará solo para DNX Core 5.0 (
"dnxcore50"
).
Uno puede verificar fácilmente que ya no tendrá ningún problema.
ACTUALIZADO 4:
Finalmente, he encontrado una solución muy simple a su problema: uno solo necesita agregar
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
dependencia
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
al proyecto:
{
"dependencies": {
"Google.Protobuf": "3.0.0-alpha4",
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
}
}
Sigue a cargar muchos dlls innecesarios, pero ahora las dependencias se resolverán correctamente.
El proyecto final se puede compilar sin problemas para dnx451 y dnxcore50. Interpreto los resultados de la siguiente manera: "Google.Protobuf" funciona con dnx451 y dnxcore50, pero la resolución automática de dependencias de RC1 todavía tiene errores y no puede resolver correctamente algunas dependencias requeridas de "Google.Protobuf".
Por la causa de agregar directamente
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
innecesario
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
referencia
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
puede verse solo como una solución.
Creo que la resolución de dependencia utilizada en ASP.NET 5 y DNX todavía tiene errores.
Publiqué un tiempo antes
del problema
, que todavía está abierto.
El problema proporciona un ejemplo cuando la resolución de
la dependencia incluida directa
puede proporcionar
otros
resultados, ya que las dependencias resueltas por
dnu restore
.
Fue la razón por la que comencé a comparar la dependencia del
código
de
trabajo
, que inicialmente publiqué con las dependencias del proyecto que no funciona.
Después de algunas pruebas, encontré la solución y la reduje a la única dependencia:
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
.