2017-10-31 19 views
6

私に適したソリューションで更新されました。この質問の下部を見てください。.NET Core&Xamarinを使用してILからコンパイルされたアセンブリを使用する

コンテキスト:
私は特定のバイトサイズ内に収まるように、配列の長さを計算する目的のための一般的な種類の大きさを評価する方法が必要でした。基本的には、 sizeofとC/C++の類似点があります。

C#のsizeofおよびMarshal.SizeOfは、多くの制限があるため、これには適していません。

これを念頭に置いて、私はsizeofオペコードで探していた機能を可能にするILにアセンブリを書きました。私はそれが本質的に参照型でIntPtr.Sizeと評価されていることを知っています。

私はこれを.NET標準&コアに複製しました。これはmscorlibの正しい同等品であると信じていました。 ILがうまくコンパイルすることに注意してください。この問題は別の問題です。

コード:ターゲットフレームワークあたり
ヘッダ:

.NET:(Windowsの\ Microsoft.NET Frameworkの\ \ v4.0.30319 ilasm.exe \)

.assembly extern mscorlib {} 

.NET標準: (nugetから抽出ILASM)

.assembly extern netstandard 
{ 
    .publickeytoken = (B7 7A 5C 56 19 34 E0 89) 
    .ver 0:0:0:0 
} 
.assembly extern System.Runtime 
{ 
    .ver 0:0:0:0 
} 

.NETコア(標準と同じILASM、しかしこのようにコンパイルされたDLLは、.NET CoreまたはXamarinアプリケーションによって参照されている場合は、私が受け取る、

.assembly Company.IL 
{ 
    .ver 0:0:1:0 
} 
.module Company.IL.dll 

// CORE is a define for mscorlib, netstandard, and System.Runtime 
.class public abstract sealed auto ansi beforefieldinit 
    Company.IL.Embedded extends [CORE]System.Object 
{ 
    .method public hidebysig specialname rtspecialname instance void 
    .ctor() cil managed 
    { 
    .maxstack 8 
    ldarg.0 
    call instance void [CORE]System.Object::.ctor() 
    ret 
    } 

    .method public hidebysig static uint32 
    SizeOf<T>() cil managed 
    { 
    sizeof !!0 
    ret 
    } 
} 

問題:私は)の両方で

.assembly extern System.Runtime 
{ 
    .ver 0:0:0:0 
} 

ソースをテストしてみました次のエラーが発生しました:

The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

このようなdllが.NETプロジェクトによって参照される場合、この問題は発生しません。 .NET標準ライブラリは、.NETプロジェクトによって参照されます。

さまざまなバージョンとアセンブリでこのエラーを詳しく説明している無数の記事、投稿、およびリポジトリを読んだことがあります。典型的な解決策は、ターゲットフレームワークのmscorlibと同等の明示的な参照を追加することです(移植性を損なう)。 .NET標準&コアのILコンパイル済みアセンブリの使用に関する情報が不足しているようです。

わかりましたように、.NET標準&コアは、タイプの定義を転送するためにファサードを使用します。これにより、ターゲットフレームワークのランタイムによって解決され、移植性が実現されます。正確に同じ参照を使用して、C#のからコンパイルSystem.Runtime

  • 分解.NETのコアライブラリの

    • 明示的なバージョン:

      は、私は次のことを試してみました。奇妙なことに、明示的なバージョン(.NET Core 2.0のSystem.Runtime 4.2など)をターゲットにしているようです。

    • Emit APIを使用してコードを動的に生成する。メモリへのコンパイルは機能しているようですが、Xamarin.iOS(AOTのみ)をターゲットにしているため、オプションではありません。このように動的にコンパイルされたアセンブリをディスクから参照すると、手動でコンパイルした場合と同じエラーになります。

    アップデート:私は(ビルド手順here以下)Jacek's answerでソリューションを試みた、まだを通じて掘った後、ビルドスクリプトやしかしVS 2017でcorefxをコンパイルするために、私のシステムを構成することができませんでした
    コードSystem.Runtime.CompilerServices.Unsafe解決策を発見しました。

    これはおそらく明らかですが、私はSystem.Runtimeの間違ったバージョンを参照していました。 (corefxからコピーされた)ターゲット・フレームワークあたり

    ヘッダ:

    .NET:

    #define CORELIB "mscorlib" 
    
    .assembly extern CORELIB {} 
    

    .NET標準:

    #define CORELIB "System.Runtime" 
    #define netcoreapp 
    
    // Metadata version: v4.0.30319 
    .assembly extern CORELIB 
    { 
        .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A) 
        .ver 4:0:0:0 
    } 
    

    .NETコア:

    #define CORELIB "System.Runtime" 
    
    // Metadata version: v4.0.30319 
    .assembly extern CORELIB 
    { 
        .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A) 
        .ver 4:0:0:0 
    } 
    

    すべてのソースファイルで、0123を使用してくださいはmscorlib(すなわち、 [CORELIB]System.Object)。

  • +0

    あなたの 'Reflection.Emit'試行の結果はどうでしたか? – thehennyy

    +0

    @thehennyy詳細については更新されました。 –

    +0

    @ KobyDuck:ILのみのアセンブリを参照するプロジェクトでコンパイルエラーを抑制するオプションを追加しました。これも同様に役立つかもしれません。 –

    答えて

    3

    DotNet CoreFXレポで正しく行う方法の非常に良い例があります。 System.Runtime.CompilerServices.UnsafeはILのみのアセンブリであり、.NET CoreおよびXamarinで使用できます。

    https://github.com/dotnet/corefx/tree/master/src/System.Runtime.CompilerServices.Unsafe

    問題には2つのアプローチがある:(i)ゼロからプロジェクトにビルド構成の必要な要素を再作成しようとする - どのように時間がかかり、非常に複雑になります - corefxビルドシステムが本当に複雑ですが(ii)System.Runtime.CompilerServices.Unsafeプロジェクトを複製し、ネーミングを変更し、ILコードをあなたのものに置き換えることによって、既存のビルドインフラストラクチャを使用し、.NETコアCoreFXレポの中にILプロジェクトを作成します。私の意見では、これはILベースのアセンブリを構築する最速の方法であり、すべてのターゲットで正しく動作することが保証されます。 .NET Coreまたは.NET標準の任意の特定のバージョンをターゲットにしながら、ちょうどリリースブランチにそれを作成し、あなたのアセンブリを構築するには

    release/2.0.0release/1.1.0など

    The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.

    ことを抑制するためにしようとするオプションがありますそれをトリガするアセンブリを参照するプロジェクトでは、コンパイルエラーだけが発生します。次のプロパティを新しい形式のcsproj/vbprojに設定すると、それが抑止されます。

    <PropertyGroup> 
        <_HasReferenceToSystemRuntime>true</_HasReferenceToSystemRuntime> 
    </PropertyGroup> 
    
    +0

    私は信じられないほど忙しく、これを試す時間がありませんでした。私はこれを後で撃ち、あなたに戻ってきます。ありがとう。 –

    +0

    私はcorefxをコンパイルできませんでしたが、あなたの答えは私にはうまくいくソリューションをもたらしました。詳細は、私の更新された質問を参照してください。あなたのソリューションは、corefxをコンパイルできる人のために働くはずです。 –

    関連する問題