2015-12-07 33 views
53

我试图验证Protocol Buffers将使用来自ASP.NET团队和理想的大多数其他现代环境的新的可移植运行时。 3.0.0-alpha4版本是在前一段时间使用profile259创建的,因此我希望在某些情况下需要进行一些更改,但我认为我会试一试。我知道Oren Novotny's post about targeting .NET Core,并且预计必须对Google.Protobuf nuspec file进行一些更改,但是我遇到的错误让我难堪。无法解决无框架组件参考问题

DNX版本:1.0.0-RC1-UPDATE1

我目前正试图测试场景是一个控制台应用定位dnx451。我有一个非常简单的示例应用程序:

using Google.Protobuf.WellKnownTypes; 
using System; 

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

...和一个小project.json

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

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

请注意,我还没有使用dnxcore*这里 - 讽刺的是,我得到了工作没有问题。

dnu restore工作正常; dnx run失败:

Error: c:\Users\Jon\Test\Projects\protobuf-coreclr\src\ProtobufTest\Program.cs(9,9): DNX,Version=v4.5.1 error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

以下变化导致相同的错误:

  • 明确添加依赖于"System.Runtime": "4.0.0"dependencies部分为框架
  • 在明确添加依赖于"System.Runtime": "4.0.0-beta-23109"dependencies部分框架,同样4.0.10-beta-*4.0.20-beta-*4.0.21-beta*
  • 添加依赖关系System.Runtime的NuGet包(本地)内和重建对抗 - project.lock.json进行了更新,包括System.Runtime V4.0.0,但发生同样的错误
  • 同上包括一个包中的lib\dotnet目录,以及作为依赖

的步骤,工作(独立,并没有dependencies项),但让我困惑:

  • 改变Console.WriteLine调用刚Console.WriteLine("foo")(但没有其他的改变)
  • 改变duration变量的类型object代替Duration
  • 卸下协议缓冲器的所有暗示完全,并且代替使用TimeSpan或类似
  • 加入以下的dnx451部分project.json:

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

最终,我不希望用户必须这样做 - 至少,不是为了Protocol Buffers。我假设这是与我们如何构建协议缓冲区有关,但由于我无法正确理解原因,因此很难修复。我期望如果我能找到一种方法来制作dependencies条目,那么我可以将该依赖添加到Protocol Buffers本身中,这很好 - 但是由于对System.Runtime v4.0.0具有依赖关系project.lock文件似乎没有帮助,我必须缺少的东西:(

+1

我打了一个非常类似的错误了一个简单的类库。找到改变project.json文件以解决问题的两种方法 - http://nodogmablog.bryanhogan.net/2016/01/the-type-is-defined-in-an-assembly-that-is-not-referenced -system-runtime/ – Bryan

回答

21

所以,如果你眯着眼睛看project.json,它基本上是一个nuspec,用一点点goop来描述构建项目所需的编译选项和源代码。今天Nuspecs有2个部分,frameworkAssemblies“内置”的东西和dependencies其他nuget依赖项。它在这里有相同的含义。当您使用“框架”中的某些内容时,需要在frameworkAssemblies中指定它作为nuget包依赖项。

现在到细节:

当您使用.NET Framework中的PCL或基于.NET的核心函数库,引用来引用组件(有时也被称为合同组件)。这些的一些例子是System.Runtime,System.Threading等。当使用基于MSBUILD的项目时,有一个任务运行,基本上会自动将的所有的引用添加到C#编译器中以避免混乱。这些程序集在.NET Framework上称为Facade。不幸的是,它增加了所有即使他们没有使用。对System.Runtime的依赖性是此行为的触发器(在基于.NET Framework的csproj文件上运行时)。

之所以加入到同一个包的引用不工作是因为那些合同组件.NET框架文件夹(NET4 *)(如System.Runtime),没有在其中任何DLL。如果你看看这些文件夹,你会看到一个空的_._文件。推理原因是因为当你声明一个frameworkAssembly参考System.Runtime的nuget包时,msbuild项目系统无法安装它(非常复杂的错误和设计问题)。

这可能使事情变得更加模糊......

+0

所以只是为了澄清,解决方案是在Google.Protobuf包中添加'frameworkAssembly'引用,并绑定到特定的目标平台? –

+0

@JonSkeet你可以像''frameworkAssemblies“一样添加它:{”System.Runtime“:{”type“:”build“,”version“:”“}}'所以它不会进入最终的nuspec文件,这应该是更清洁的解决方案。 –

+0

@AxelHeer:我现在只用'“type”:“build”来包含源代码......对于框架程序集来说意味着什么?你是建议把它放在Protobuf nuspec文件中,还是放在我的控制台应用程序的project.json中? –

5

在我看来,你的问题存在,只是因为你选择了控制台应用程序,而不是“ASP.NET Web应用程序”/“ ASP.NET 5模板“/”空“我做了简单的测试用法空模板,从NuGet添加了"Google.Protobuf": "3.0.0-alpha4",最后修改为Startup.cs,以便它使用Google.Protobuf.WellKnownTypes

  • 加入using Google.Protobuf.WellKnownTypes;
  • 加入var duration = new Duration { Seconds = 100, Nanos = 5555 };内部的Configure
  • 改性await context.Response.WriteAsync("Hallo World!");await context.Response.WriteAsync(duration.ToString());

Startup.cs最后的代码:

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

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

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

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

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

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

所得ASP.NET 5应用程序成功显示100.5555s在网页浏览器中。

您可以从here下载演示项目。

更新:我分析了纯控制台DNX应用程序,它使用的代码,可以发现问题的的原因在duration.ToString()方法,这在ASP.NET环境下工作,但不能在纯控制台问题应用。这个问题的原因是有趣的,我试图调查,但我想分享我目前的结果等

我可以做的工作如下代码:

using Google.Protobuf.WellKnownTypes; 
using System; 

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

一个可以下载的工作项目从here

我另外注释行

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

AssemblyInfo.cs为没有不需要的参考"Microsoft.CSharp",它有很多的其他参考文献。该project.json包含在演示项目:

{ 
    ... 

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

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

通过包括在"frameworks""dnxcore50"部分"System.Console": "4.0.0-beta-23516"因为Console命名空间(Console.WriteLine)在DNX 4.5.1mscorlib存在需要的方式。如果一个人会尝试对共同的依赖程度增加"System.Console": "4.0.0-beta-23516"一送开头的错误与文本

Error CS0433 The type 'Console' exists in both 'System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' ConsoleApp3.DNX 4.5.1

更新2:可以换线

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

Console.WriteLine((object)duration); 

使其工作。只是使用Console.WriteLine(duration);var str = duration.ToString();会产生您描述的错误。

更新1:我验证码duration.ToString()电话the lines其使用the lines进行格式化。看起来代码duration.ToString()WellKnownTypes类型确实与((object)duration).ToString()相同(如Duration)。

我认为重要的最新评论。所描述的问题仅适用于dnx451(或dnx452或dnx46)。如果一个将project.json"frameworks"部分删除线

"dnx451": { }, 

那么程序将是用于编译DNX核心5.0只("dnxcore50")。人们可以很容易地验证一个人会没有任何问题。

更新1:最后我发现很简单的解决方法,您的问题为:一是需要只需添加"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"依赖于项目:

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

它遵循以加载许多不必要的dll,但现在的依赖性将会做得正确的解决。

The final project可以在没有任何问题的情况下编译为dnx451和dnxcore50。我将结果解释如下:“Google.Protobuf”可以同时使用dnx451和dnxcore50,但RC1的自动依赖关系解析仍然存在问题,并且无法正确解析“Google.Protobuf”的一些必需依赖关系。

因为直接添加不需要的"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"参考可以被视为一种解决方法只。我认为ASP.NET 5和DNX中使用的依赖关系解决方案仍然存在问题。我在the issue之前发布了一段时间,它仍然是开放的。该问题提供了一个例子,当解决直接包含依赖关系可以提供另一个结果作为依赖关系由dnu restore解决。这就是为什么我开始比较工作代码的依赖关系的原因,我首先发布了它与非工作项目的依赖关系。经过一些测试后,我找到了解决方法,并将其减少到唯一的依赖项:"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"

+0

但我希望图书馆能够在控制台应用程序以及网络应用程序中工作。重点是,它的意图是可移植的......当我说“ASP.NET v5”时,我的意思是所有的方式...... ASP.NET似乎比网络应用程序这些日子更多...将澄清问题。 –

+0

你写了关于“ASP.NET v5”。你想用DNX Core 5.0进行测试吗?如果您确实需要“ASP.NET v5”应用程序,并且您不想在控制台内部运行,则应该更改应用程序的开始。 Project.json具有“”Microsoft.AspNet.Server.Kestrel“作为依赖关系,”web“作为”command“。它允许在控制台应用程序中以自主方式启动应用程序。必须仍然使用和以前一样的ASP.NET应用程序。人们会看到结果不是在控制台上,而是在结婚浏览器中(在客户端)。 – Oleg

+0

我想用各种运行时测试它,使用由ASP.NET v5团队构建的新运行时环境。 dnxcore50已经工作,这就是为什么它不在我的问题。我目前对Web应用程序不感兴趣 - 我正在尝试使用dnx451目标来获取控制台应用程序,按照project.json。 –

8

我已接受David Fowler's answer为理由为什么所有发生的这一切。现在的我应该这件事而言,它看起来像我只需要在nuspec文件中添加frameworkAssemblies元素Google.Protobuf:在客户端

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

frameworkAssembly引用然后结束了在project.lock.json项目,一切都很好。

然而,大卫的其他评论判断(“我们要看看这个固定”),我可能不需要反正做什么...

+0

这些信息对于NuGet包的开发者来说似乎很有趣。将更多标签(nuget,nuspec等)添加到您的问题中可能会更好,从而更好地索引和找到信息。 – Oleg

+0

@ Oleg:看起来很合理。完成。 –