我们有一个相当大的共享项目,可以说有3个头:
这三个引用了可移植库,它们同时针对Windows 8.1和Windows Phone 8.1。
使用本机工具链编译UWP项目时,可移植库无法访问任何类型信息,因此无法执行任何反射。
失败的方法是通用方法,并检查typeof(T)
以根据其类型执行各种操作。
抛出System.NotImplementedException
的第一行是:
If (typeof(T).IsArray)
在这种情况下,T是System.String
,如果我在失败的方法上打破调试器并输入visual studio 2015的即时窗口,我得到:
>> typeof(string).IsArray
An internal error has occurred while evaluating method System.Type.get_IsArray().
但是,如果我在App.OnLaunched方法中执行相同操作,则可以正常工作。因此,即使是System.String
等系统类型,便携式库也无法访问任何类型的信息。
我尝试为便携式库添加平台指令,但到目前为止还没有运气。
您是否有任何有关如何启用便携式库以访问类型信息的信息。
答案 0 :(得分:2)
我通过电子邮件回复了微软在微软的回复,解释了根本原因以及如何解决这个问题。
您似乎遇到了此处描述的相同问题: https://github.com/dotnet/corert/issues/3565,除了中的方法 问题是Type.IsArray而不是ConstructorInfo.Invoke。
问题是Type.IsArray方法被声明为非虚拟 在您的源代码编译的可移植库合同中 反对,但它在implementation assemblies中使用的是虚拟的 .NET Native。这通常不是一个大问题,因为C# 编译器几乎总是使用“callvirt”指令来调用 方法(即使它不是虚拟的)。 Visual中附带的C#编译器 Studio 2017开始进行优化,如果方法不是 虚拟和传递给该方法的'this'已知不为null , 它使用“call”而不是“callvirt”。结果是代码结束 调用一个永远不应该调用的方法。的结果 已知typeof()表达式永远不会为空。
好消息是我们将IsArray non-virtual again作为其中的一部分 NetStandard 2.0的努力。坏消息是.NET Native支持 对于NetStandard 2.0尚未发货。
您需要一种解决方法。我能想到的最简单的是添加一个 扩展方法,并改为使用:
static class NetNativeWorkarounds { public static bool IsArray(this Type type) => type.IsArray; }
使用扩展方法可以避免C#编译器优化,因为 此条件未得到满足(编译器不知道您将使用哪种类型 传递给扩展方法,并且必须做一个callvirt Type.IsArray方法)。