我正在尝试验证Protocol Buffers是否适用于ASP.NET团队的新移植运行时,以及大多数其他现代环境.3.0.0-alpha4版本是前一段时间使用profile259创建的,所以我希望在某些情况下需要进行一些更改,但我想我会尝试一下.我知道Oren Novotny关于针对.NET Core的帖子,并且预计必须对Google.Protobuf nuspec文件进行一些更改,但是我遇到的错误让我感到难过.
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:类型'Object'在程序集中定义没有引用.您必须添加对程序集'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
呼叫更改为just Console.WriteLine("foo")
(但没有其他更改)
将duration
变量的类型更改为object
而不是Duration
完全删除所有协议缓冲区的提示,而不是使用TimeSpan
或类似
在以下dnx451
部分中将以下内容添加到project.json :
"frameworkAssemblies": { "System.Runtime": "" }
最终,我不希望用户必须这样做 - 至少,不是为了协议缓冲区.我假设这是东西做我们如何构建Protocol Buffers的,但我不正确理解的原因,就很难解决.
我希望如果我能找到一种使dependencies
入口工作的方法,那么我可以将该依赖项添加到Protocol Buffers本身,这很好 - 但是在project.lock文件中依赖于System.Runtime v4.0.0似乎没有帮助,我必须遗漏一些东西:(
因此,如果你眯着眼睛看看project.json,它基本上是一个带有一点goop的nuspec来描述构建项目所需的编译选项和源代码.Nuspecs今天有2个部分,frameworkAssemblies
用于"内置"的东西和dependencies
其他nuget依赖项.它具有相同的含义.当您使用"框架"中的内容时,需要在frameworkAssemblies
vs中指定为nuget包依赖项.
现在详细说明:
在.NET Framework上使用基于PCL或.NET Core的库时,引用将引用程序集(有时称为契约程序集).其中的例子是一样的东西System.Runtime
,System.Threading
等等.当使用基于MSBUILD项目,有运行,基本上会自动添加一个任务,所有的的System.*
引用到C#编译器来避免这个烂摊子.这些程序集在.NET Framework上称为外观.不幸的是,即使不使用它们,它也会添加所有这些.依赖性System.Runtime
是此行为的触发器(在基于.NET Framework的csproj文件上运行时).
添加对同一个包的引用的原因不起作用是因为这些契约程序集(如System.Runtime)的.NET Framework文件夹(net4*)中没有任何dll.如果查看这些文件夹,您将看到一个空_._
文件.这样做的原因是因为当你声明一个带有frameworkAssembly
引用的nuget包时System.Runtime
,msbuild项目系统无法安装它(非常复杂的bug和设计问题).
这可能会让事情更加模糊......
我已经接受大卫·福勒的回答为理由,为什么这一切发生.现在就我应该做些什么而言,看起来我只需要frameworkAssemblies
在nuspec文件中添加一个元素Google.Protobuf
:
... ...
frameworkAssembly
然后,该引用最终出现在project.lock.json
客户端项目中,一切都很顺利.
然而,根据大卫的其他评论判断("我们将考虑解决这个问题")无论如何我可能不需要做任何事情......
在我看来,您的问题只是因为您选择了控制台应用程序而不是"ASP.NET Web应用程序"/"ASP.NET 5模板"/"空".我做了简单的测试用法空模板,"Google.Protobuf": "3.0.0-alpha4"
从NuGet 添加,最后只是修改,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(args); } }
生成的ASP.NET 5应用程序100.5555s
在Web浏览器中成功显示.
您可以从这里下载演示项目.
更新:我分析了纯控制台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); } } }
可以从这里下载工作项目.
我另外评论了这条线
//[assembly: Guid("b31eb124-49f7-40bd-b39f-38db8f45def3")]
in 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"
,因为名称空间(for )存在于其中所以需要包含"dnxcore50"
部分内容.如果有人试图添加公共依赖项的级别,则会在文本的开头处获得错误"frameworks"
Console
Console.WriteLine
mscorlib
DNX 4.5.1
"System.Console": "4.0.0-beta-23516"
错误CS0433类型'控制台'同时存在于'System.Console,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a'和'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()
调用的线条,其使用的线路进行格式化.看来这个代码duration.ToString()
确实真的一样((object)duration).ToString()
的WellKnownTypes
类型(如Duration
).
我发现最新的评论很重要.所描述的问题仅存在于dnx451(或dnx452或dnx46).如果有人会删除这些行
"dnx451": { },
从"frameworks"
部分project.json
程序开始,程序将仅为DNX Core 5.0编译("dnxcore50"
).人们可以轻松验证一个人不会有任何问题.
更新4:最后我找到了解决问题的非常简单的方法:只需要"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
为项目添加依赖项:
{
"dependencies": {
"Google.Protobuf": "3.0.0-alpha4",
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
}
}
接下来加载许多不需要的dll,但现在依赖关系将被正确解析.
对于dnx451和dnxcore50,可以编译最终项目而不会出现任何问题.我将结果解释如下:"Google.Protobuf"同时适用于dnx451和dnxcore50,但是RC1的自动依赖性解析仍然存在问题,并且它无法正确解析"Google.Protobuf"的某些必需依赖项.
因为直接添加不需要的"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
引用可以被视为仅一种解决方法.我认为ASP.NET 5和DNX中使用的依赖项解析仍然存在问题.我在问题发布之前发布了一段时间,但仍未解决.该问题提供了一个示例,当解析直接包含的依赖关系可以提供另一个结果作为依赖关系解析dnu restore
.这就是为什么我开始比较工作代码的依赖性的原因,我最初将这些代码与非工作项目的依赖关系进行了比较.经过一些测试后,我找到了解决方法并将其减少为唯一的依赖:"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
.