我试图验证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
失败了:
错误:c:\ Users \ Jon \ Test \ Projects \ protobuf-coreclr \ src \ ProtobufTest \ Program.cs(9,9):DNX,Version = v4.5.1 error CS0012:Type' Object& #39;在未引用的程序集中定义。您必须添加对程序集的引用,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
添加依赖项(本地)并重新构建 - 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": ""
}
最终,我不希望用户必须这样做 - 至少,不是为了协议缓冲区。我假设这是某些与我们如何构建协议缓冲区有关,但由于我不能正确理解原因,因此很难解决
我希望如果我能够找到一种使dependencies
条目工作的方法,那么我可以将该依赖项添加到Protocol Buffers本身,这很好 - 但是因为它依赖于System.Runtime v4 project.lock文件中的.0.0似乎没有帮助,我必须遗漏一些东西:(
答案 0 :(得分:21)
因此,如果你眯着眼睛看看project.json,它基本上是一个带有一点goop的nuspec来描述构建项目所需的编译选项和源代码。 Nuspecs今天有2个部分,frameworkAssemblies
表示“内置”内容,dependencies
代表其他nuget依赖项。它具有相同的含义。当您使用“框架”中的内容时,需要在frameworkAssemblies
中指定vs作为nuget包依赖项。
现在详细说明:
在.NET Framework上使用基于PCL或.NET Core的库时,引用是引用程序集(有时称为合同程序集)。这些例子包括System.Runtime
,System.Threading
等。当使用基于MSBUILD的项目时,有一个任务运行,基本上自动添加{em>所有 {{1}引用C#编译器以避免这种混乱。这些程序集在.NET Framework上称为外观。不幸的是,即使不使用它们,它也会添加 ALL 。对System.*
的依赖是此行为的触发器(在基于.NET Framework的csproj文件上运行时)。
添加对同一个包的引用的原因不起作用是因为这些契约程序集(如System.Runtime)的.NET Framework文件夹(net4 *)中没有任何dll。如果查看这些文件夹,您将看到一个空的System.Runtime
文件。这样做的原因是因为当你声明一个_._
引用frameworkAssembly
的nuget包时,msbuild项目系统无法安装它(非常复杂的bug和设计问题)。
这可能会让事情更加模糊......
答案 1 :(得分:8)
我已接受David Fowler's answer作为为什么所有这一切发生的原因。现在就我应该做什么而言,看起来我只需要在frameworkAssemblies
的nuspec文件中添加Google.Protobuf
元素:
<package>
<metadata>
...
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Runtime" targetFramework="net45" />
</frameworkAssemblies>
</metadata>
...
</package>
frameworkAssembly
引用最终会出现在客户端项目的project.lock.json
中,一切都很顺利。
然而,根据大卫的其他评论判断(&#34;我们将考虑修复此问题&#34;)我可能不需要做任何事情......
答案 2 :(得分:5)
在我看来,您的问题的存在只是因为您选择了控制台应用程序而不是&#34; ASP.NET Web应用程序&#34; /&#34; ASP.NET 5模板&#34; /&#34;空&#34;。我制作了简单的测试用法空模板,从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应用程序在Web浏览器中成功显示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"
}
}
}
}
顺便说一下"System.Console": "4.0.0-beta-23516"
"dnxcore50"
部分包括"frameworks"
,因为Console
名称空间(Console.WriteLine
)存在于mscorlib
的{{1}}中DNX 4.5.1
。如果有人试图在常见依赖关系的级别上添加"System.Console": "4.0.0-beta-23516"
,则会在文本开头时出现错误
错误CS0433类型&#39;控制台&#39;存在于&#39; System.Console中, Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a&#39;和 &#39; mscorlib,版本= 4.0.0.0,文化=中立, 公钥= b77a5c561934e089&#39; 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();
会产生您所描述的错误。
更新3 :我确认代码duration.ToString()
使用the lines调用the lines进行格式化。似乎代码duration.ToString()
与((object)duration).ToString()
类型的WellKnownTypes
实际上相同(例如Duration
)。
我觉得最重要的最新评论。所描述的问题仅存在于dnx451(或dnx452或dnx46)。如果有人删除行
"dnx451": { },
来自"frameworks"
的{{1}}部分,然后该程序将仅针对DNX Core 5.0进行编译(project.json
)。人们可以很容易地确认一个人不会有任何问题。
更新4:最后,我发现了一个非常简单的问题解决方法:只需要为项目添加"dnxcore50"
依赖项:
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
接下来加载许多不需要的dll,但现在依赖关系将被正确解析。
对于dnx451和dnxcore50,可以编译The final project而不会出现任何问题。我将结果解释如下:&#34; Google.Protobuf&#34;同时使用dnx451和dnxcore50,但是RC1的自动依赖性解析仍然存在问题,并且它无法正确解析某些必需的依赖关系&#34; Google.Protobuf&#34;。
原因是直接添加不需要的{
"dependencies": {
"Google.Protobuf": "3.0.0-alpha4",
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
}
}
引用只能被视为一种解决方法。我认为ASP.NET 5和DNX中使用的依赖项解析仍然存在问题。我在the issue之前发布了一段时间,但仍然打开了。当直接包含依赖的解析可以提供另一个结果作为"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
解析的依赖关系时,该问题提供了一个示例。这就是为什么我开始比较工作代码的依赖性,我最初发布的是与非工作项目的依赖关系。经过一些测试后,我找到了解决方法,并将其减少为唯一的依赖项:dnu restore
。