53 votes

Impossible de résoudre le problème de référence d'assemblage sans frameworkAssemblies

J'essaie de valider que Tampons de protocole va fonctionner avec les nouveaux runtimes portables de l'équipe ASP.NET et, idéalement, avec la plupart des autres environnements modernes. La version 3.0.0-alpha4 a été créée il y a un certain temps à l'aide de profile259, je m'attends donc à ce que des modifications soient nécessaires dans certains cas, mais j'ai pensé que je devais faire un essai. Je suis au courant de Le billet d'Oren Novotny sur le ciblage de .NET Core et je m'attendais à devoir apporter quelques modifications à l'interface de l'entreprise. Fichier nuspec Google.Protobuf mais l'erreur que je rencontre me laisse perplexe.

Version du DNX : 1.0.0-rc1-update1

Le scénario que j'essaie actuellement de tester est une application console ciblant le dnx451. J'ai un exemple d'application très 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);
    }
}

... et un petit project.json :

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

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

Notez que je n'utilise même pas dnxcore* ici - ironiquement, j'ai que pour fonctionner sans problème.

dnu restore fonctionne bien ; dnx run échoue avec :

Erreur : c : \Users\Jon\Test\Projects\protobuf -coreclr \src\ProtobufTest\Program.cs (9,9) : DNX,Version=v4.5.1 erreur CS0012 : Le type 'Object' est défini dans un assembly qui n'est pas référencé. Vous devez ajouter une référence à l'assemblage 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

Les modifications suivantes entraînent la même erreur :

  • Ajouter explicitement une dépendance à "System.Runtime": "4.0.0" dans le dependencies section pour le cadre
  • Ajouter explicitement une dépendance à "System.Runtime": "4.0.0-beta-23109" dans le dependencies pour le cadre, et de même pour 4.0.10-beta-* , 4.0.20-beta-* y 4.0.21-beta* .
  • Ajout de dépendances à System.Runtime à l'intérieur du paquet NuGet (localement) et la reconstruction par rapport à cela - project.lock.json a été mis à jour pour inclure System.Runtime v4.0.0, mais la même erreur s'est produite
  • Idem, y compris un lib\dotnet dans le paquet, ainsi que les dépendances

Des étapes qui a fait travail (de manière indépendante, et sans dependencies ), mais m'embrouillent :

  • Changer le Console.WriteLine appel à juste Console.WriteLine("foo") (mais pas d'autres changements)
  • Changer le type de duration à la variable object au lieu de Duration
  • Suppression de toute allusion aux tampons de protocole et utilisation de l'option TimeSpan ou similaire
  • Ajouter ce qui suit au fichier project.json dans le fichier dnx451 section :

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

En fin de compte, je ne veux pas que les utilisateurs aient à faire cela - du moins, pas pour le bien des tampons de protocole. Je suppose que c'est quelque chose Cela a un rapport avec la façon dont nous construisons les tampons de protocole, mais comme je ne comprends pas bien la cause, c'est difficile à résoudre.

Je pense que si je parvenais à trouver un moyen de faire un dependencies Je pourrais alors ajouter cette dépendance dans Protocol Buffers lui-même, ce qui serait parfait - mais comme avoir une dépendance sur System.Runtime v4.0.0 dans le fichier project.lock ne semble pas aider, je dois manquer quelque chose :(

21voto

dfowler Points 16530

Si vous louchez et regardez le project.json, il s'agit essentiellement d'un nuspec avec un peu de goop pour décrire les options de compilation et les sources nécessaires pour construire le projet. Les nuspecs ont aujourd'hui 2 sections, frameworkAssemblies pour les éléments "intégrés" et dependencies pour les autres dépendances nuget. Cela a la même signification ici. Lorsque vous utilisez un élément du "framework", il doit être spécifié dans le fichier frameworkAssemblies plutôt que d'être une dépendance d'un paquet nuget.

Passons maintenant aux détails :

Lorsque vous utilisez une bibliothèque PCL ou .NET Core sur .NET Framework, les références sont des assemblages de référence (parfois appelés assemblages de contrat). Il s'agit par exemple de choses comme System.Runtime , System.Threading etc. Lorsque vous utilisez des projets basés sur MSBUILD, une tâche s'exécute et ajoute automatiquement les éléments suivants todo de la System.* au compilateur C# pour éviter ce désordre. Ces assemblages sont appelés façades sur .NET Framework. Ce qui est regrettable, c'est que cela ajoute TOUTES d'eux même s'ils ne sont pas utilisés. Une dépendance à System.Runtime est le déclencheur de ce comportement (lors de l'exécution sur des fichiers csproj basés sur .NET Framework).

La raison pour laquelle l'ajout d'une référence au même paquetage ne fonctionne pas est que le dossier .NET Framework (net4*) de ces assemblages de contrat (comme System.Runtime) ne contient aucune dll. Si vous regardez ces dossiers, vous verrez un dossier vide de type _._ fichier. Cela s'explique par le fait que lorsque vous déclarez un paquet nuget avec une balise frameworkAssembly référence à System.Runtime le système de projet msbuild ne parvient pas à l'installer (bug très compliqué et problème de conception).

Cela a probablement rendu les choses plus floues...

8voto

Jon Skeet Points 692016

J'ai accepté La réponse de David Fowler comme la raison pourquoi tout cela est arrivé. Maintenant, en termes de ce que je devrais faire à ce sujet, il semble que j'ai juste besoin d'ajouter une frameworkAssemblies dans le fichier nuspec pour Google.Protobuf :

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

Ce frameworkAssembly se retrouve ensuite dans la référence project.lock.json dans le projet du client, et tout va bien.

Cependant, à en juger par l'autre commentaire de David ("Nous allons chercher à corriger ce problème"), il se peut que je n'aie rien à faire de toute façon...

5voto

Oleg Points 136406

Il me semble que votre problème n'existent que parce que vous avez choisi d'application de la Console au lieu de "ASP.NET l'Application Web" / "ASP.NET 5 Modèles de" / "à Vide". J'ai fait un test simple d'utilisation modèle Vide, ont ajouté "Google.Protobuf": "3.0.0-alpha4" de NuGet et enfin juste modifié Startup.cs afin qu'il utilise Google.Protobuf.WellKnownTypes:

  • ajouté using Google.Protobuf.WellKnownTypes;
  • ajouté var duration = new Duration { Seconds = 100, Nanos = 5555 }; à l'intérieur de l' Configure
  • modifiés await context.Response.WriteAsync("Hallo World!"); de await context.Response.WriteAsync(duration.ToString());

La version finale du code de l' 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);
    }
}

Le résultant ASP.NET 5 application affichée avec succès 100.5555s dans le navigateur web.

Vous pouvez télécharger le projet de démonstration à partir d' ici.

Mise à JOUR: j'ai analysé le problème avec pure console DNX application, qui utilise le code et pourrait trouvé la raison du problème en duration.ToString() méthode, qui fonctionne dans ASP.NET de l'environnement, mais pas dans la pure application de Console. La raison du problème est intéressante et je vais essayer d'enquêter, mais je voulais partager mes résultats avec d'autres

J'ai pu faire travailler le code suivant:

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);
        }
    }
}

On peut télécharger le projet de travail à partir d' ici.

J'ai fait remarquer, en outre, la ligne de

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

en AssemblyInfo.cs n'ont aucun inutiles référence à l' "Microsoft.CSharp", qui ont beaucoup d'autres références. L' project.json contient dans le projet de démonstration:

{
  ...

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

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

Par la façon dont "System.Console": "4.0.0-beta-23516" en "dnxcore50" partie "frameworks" est nécessaire car l' Console d'espace de noms ( Console.WriteLine) existent en mscorlib de DNX 4.5.1. Si l'on veut essayer d'ajouter "System.Console": "4.0.0-beta-23516" sur le niveau de la commune de dépendances-en un et obtenez l'erreur commence avec le texte

Erreur CS0433 Le type "Console", existe dans les deux Système.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' et 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' ConsoleApp3.DNX 4.5.1

Mise à JOUR 2: On peut remplacer la ligne

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

pour

Console.WriteLine((object)duration);

pour le faire fonctionner. Juste l'utilisation de l' Console.WriteLine(duration); ou var str = duration.ToString(); produit l'erreur, que vous avez décrit.

Mise à JOUR 3: j'ai vérifié que le code duration.ToString() appels les lignes qui utilisent les lignes pour la mise en forme. Il semble que le code duration.ToString() n'est vraiment qu' ((object)duration).ToString() pour WellKnownTypes types (comme Duration).

La dernière remarque que je trouve important. Le problème décrit n'existent que pour dnx451 (ou dnx452 ou dnx46). Si l'on veut supprimer les lignes

"dnx451": { },

d' "frameworks" partie project.json puis le programme va être compile pour DNX Core 5.0 seulement ("dnxcore50"). On peut facilement vérifier qu'il n'ont pas de problème de plus.

Mise à JOUR 4: Enfin j'ai trouvé de solution simple à votre problème: on a juste besoin d'ajouter "Microsoft.AspNet.Hosting": "1.0.0-rc1-final" de dépendance pour le projet:

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

Il suit de chargement beaucoup d'inutiles dll, mais maintenant, les dépendances seront faites correctement résolu.

Le projet final peut être compilé sans problème pour les deux dnx451 et dnxcore50. - Je interpréter les résultats comme suit: "de Google.Protobuf" faire travailler à la fois sur dnx451 et dnxcore50, mais le automatique de la dépendance de la résolution de la RC1 est encore buggé et il ne peut pas correctement se résout certaines dépendances nécessaires de la "Google.Protobuf".

La cause de l'ajouter directement inutiles "Microsoft.AspNet.Hosting": "1.0.0-rc1-final" de référence peut être considérée comme une solution de contournement. Je pense que la résolution des dépendances utilisées dans ASP.NET 5 et DNX est encore buggé. J'ai posté quelques temps avant la question, qui est toujours ouvert. La question fournit un exemple lors de la résolution du direct inclus dépendance peut fournir un autre résultats comme des dépendances résolues par dnu restore. C'est la raison pour laquelle j'ai commencé à comparer la dépendance de code de travail, que j'ai posté vous d'abord avec les dépendances de non-travail du projet. Après quelques tests, j'ai trouvé la solution et l'a réduit à la seule dépendance: "Microsoft.AspNet.Hosting": "1.0.0-rc1-final".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X