用于UWP的.NET本机工具链在可移植库中引发NotImplementedException

时间:2017-05-16 10:37:42

标签: c# .net visual-studio uwp

我们有一个相当大的共享项目,可以说有3个头:

  • Windows.UWP
  • Windows.Desktop81
  • Windows.Phone81

这三个引用了可移植库,它们同时针对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等系统类型,便携式库也无法访问任何类型的信息。

我尝试为便携式库添加平台指令,但到目前为止还没有运气。

您是否有任何有关如何启用便携式库以访问类型信息的信息。

1 个答案:

答案 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方法)。