2017-05-16 5 views
2

私たちは、いわば3頭を持っている、非常に大規模な共有プロジェクトで、持っている:NETネイティブツールチェーンは、ポータブルライブラリでNotImplementedExceptionをスロー

  • Windows.UWP
  • Windows.Desktop81
  • のWindowsを。 Phone81

これら3つは、Windows 8.1とWindows Phone 8.1の両方を対象とするポータブルライブラリを指します。

ネイティブツールチェーンを使用してUWPプロジェクトをコンパイルすると、移植可能なライブラリはどのタイプ情報にもアクセスできないため、リフレクションは実行できません。

故障している方法は一般的なもので、種類によってはさまざまな操作を行うようにtypeof(T)を検査します。 System.NotImplementedExceptionをスロー

最初の行は次のようになります。この場合、

If (typeof(T).IsArray) 

、TはSystem.Stringある、と私は、Visual Studio 2015のイミディエイトウィンドウに失敗した方法とタイプのデバッガを破るならば、私が取得します:

ただし、私がApp.OnLaunchedメソッドで同じことを行うと、正常に動作します。したがって、可搬型ライブラリは、System.Stringのようなシステムタイプであっても、どのタイプ情報にもアクセスすることができません。

ポータブルライブラリのプラットフォームディレクティブを追加しようとしましたが、これまでのところ運がありません。

ポータブルライブラリがタイプ情報にアクセスできるようにする方法に関する情報はありますか。

答えて

2

私はMicrosoftのMichalから電子メールで返信を受け、根本的な原因とその回避方法を説明しました。

あなたはここで説明したのと同じ問題を打つように見える: https://github.com/dotnet/corert/issues/3565、 問題の方法はType.IsArray代わりのConstructorInfo.Invokeである点が異なります。

問題は、メソッドType.IsArrayは、ソースコードをコンパイルに対して ポータブルライブラリ契約における非仮想 として宣言されていることですが、それは .NETネイティブで使用implementation assembliesで仮想です。 C# コンパイラは、ほとんどの場合、(仮想でない場合でも) メソッドを呼び出すために、ほとんど常に "callvirt"命令を使用するため、これは大きな問題ではありません。 Visual Studio 2017に出荷されたC#コンパイラは、メソッドが 仮想ではなく、でない場合、メソッドに渡された 'this'がnullでないことがわかっている最適化を開始しました、 "callvirt" 。その結果、コードは決して呼び出されてはならないメソッドを呼び出して終了します。 の結果、typeof()式は決してnullではないことが分かっています。

良いニュースは、私たちが NetStandard 2.0の取り組みの一環としてIsArray non-virtual againを作ったことです。悪いことに、Net Standard 2.0用の をサポートする.NETネイティブはまだ出荷されていません。

回避策が必要です。私は考えることができる最も簡単で 拡張メソッドを追加し、代わりにそれを使用することです: はこの条件が満たされていないため、拡張メソッドを使用して

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

C#コンパイラの最適化を回避(コンパイラは知りませんどのようなタイプの が拡張メソッドに渡され、 Type.IsArrayメソッドへのcallvirtを実行しなければなりません。

関連する問題