2017-05-16 57 views
2

我們有相當大的共享項目,其中有3頭可以這麼說:NET原生工具鏈UWP拋出NotImplementedException便攜式圖書館

  • 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這樣的系統類型。

我已經嘗試添加便攜式庫的平臺指令,但到目前爲止沒有運氣。

您是否有關於如何啓用便攜式庫來訪問類型信息的任何信息。

回答

2

我在微軟通過電子郵件收到了Michal的回覆,解釋了根本原因以及如何避開它。

你似乎打這裏所描述的同樣的問題: https://github.com/dotnet/corert/issues/3565,除了在 問題的方法是Type.IsArray而不是ConstructorInfo.Invoke。

的問題是,該方法Type.IsArray被聲明爲在你的源代碼編譯 對移植庫合同非虛 ,但它是在 .NET本機使用的虛擬implementation assemblies。這通常不是一個大問題,因爲C# 編譯器幾乎總是使用「callvirt」指令調用 方法(即使它不是虛擬的)。在Visual Studio 2017中發佈的C#編譯器開始進行優化,如果方法不是 虛擬和傳遞給該方法的「this」已知不爲空, 它使用「call」而不是「callvirt」 。結果是代碼結束了 ,調用了一個永遠不會被調用的方法。已知typeof()表達式的結果爲 從不爲空。

好消息是,我們將IsArray non-virtual again作爲NetStandard 2.0工作的一部分,作爲 的一部分。壞消息是,支持NetStandard 2.0的支持 的.NET Native尚未發貨。

您需要一種解決方法。我能想到的最簡單的就是添加一個 擴展方法和使用,而不是:

static class NetNativeWorkarounds 
{ 
    public static bool IsArray(this Type type) => type.IsArray; 
} 

使用擴展方法避免了C#編譯器的優化,因爲 這個條件不滿足(編譯器不知道你會通過什麼類型的 傳遞給擴展方法,並且必須對 Type.IsArray方法做一個callvirt)。