2009-08-22 5 views
97

間の循環参照があります。Microsoftは循環参照を持つアセンブリをどのように作成しましたか? .NET BCLで

  • System.dllSystem.Xml.dll
  • System.dllSystem.Configuration.dll
  • System.Xml.dllSystem.Configuration.dll

はここで何を示し.NETリフレクターからのスクリーンショットです私は:

enter image description here

Microsoftがこれらのアセンブリをどのように作成したかは、私にとって謎です。これを可能にするために特別なコンパイルプロセスが必要ですか?面白いことがここで起こっていると思います。

+2

非常に良い質問です。私は実際にこれを検査するために時間をかけたことはありませんでしたが、私は答えを知りたいのです。確かに、それはダイカムが賢明なものを提供したようです。 – Noldorin

+3

なぜこれらのdllは互いに必要な場合、それらのdllは1つに統合されませんか?実用的な理由はありますか? –

+1

興味深い質問...私はエリックリッペルトの答えを知りたいです! Andreasが言ったように、なぜ彼らは同じアセンブリにすべてを入れていないのだろう... –

答えて

53

私は、Mono Projectがこれをどのようにしているかを知ることができます。定理は非常に単純ですが、コードが混乱します。

まずSystem.Configuration.dllをコンパイルし、System.Xml.dllへの参照を必要としません。その後、通常の方法でSystem.Xml.dllをコンパイルします。今や魔法がかかります。 System.config.dllを、System.Xml.dllへの参照を必要とする部分で再コンパイルします。今では循環参照とのコンパイルに成功しました。要するに

:Aコード 必要B及びB.

  • Bを参照せずにコンパイルされ

    • がコンパイルされています。
    • Aが再コンパイルされます。
  • +0

    Visual Studioによってブロックされますが、コマンドラインコンパイラ(csc.exe)を使用して直接実行できます。私の答えを見てください。 –

    +14

    私は知っています。 Monoの主なビルドシステムはVisual Studioではありません。マイクロソフトもそうではないと思う。 – Dykam

    6

    私は、非循環型のアセンブリから始め、ILMergeを使って小さなアセンブリを論理的に関連するグループにまとめることで可能になると思います。

    1

    考えられるアプローチの1つは、条件付きコンパイル(#if)を使用して、他のアセンブリに依存しないSystem.dllをまずコンパイルし、次に他のアセンブリをコンパイルし、最後にSystem.dllを再コンパイルしてXmlとConfigurationに依存します。

    +1

    残念ながら、これは条件付きでアセンブリを参照することを許可していません(私はそれが可能であれば、私のプロジェクトの1つに本当に役立つでしょう...) –

    +1

    条件リファレンスは、.csprojファイルを編集することで簡単に行うことができます。 Condition属性を要素に追加するだけです。 – Daniel

    4

    私はWindowsでこれをやったことはありませんが、実用的な前駆細胞として役立つ多くのコンパイルリンクrtl環境で行っています。あなたがやることは、最初に相互参照とリンクのないスタブ "ターゲット"を作成し、循環参照を追加してからリンクを張ることです。リンカーは一般的に、循環参照または参照チェーンに関心を持つことはなく、それぞれの参照をそれ自身で解決できるかどうかだけを気にします。へレフリーと

  • B.
  • にリンクB を任意の参照文献なし

    1. リンクA:あなたがお互いを参照する必要がある2つのライブラリー、AとBがある場合

      ので、このような何かを試してみてくださいA.

    2. リンクA、Bへの参照を追加

    Dykamは良い点を作る、それは.NETのリンクではなく、コンパイルだが、原理は同じまま:そのエクスポートされたエントリポイントを持つが、すべてを1つだけ残して、あなたの相互参照のソースを作ります彼らは他の人への自分の参照を持っています。そのように構築してください。次に、外部参照をアンスタブして再構築します。これは特別なツールがなくても動作するはずです。実際、このアプローチは、これまで試したことのあるオペレーティングシステム(約6つ)で動作しています。明らかにそれを自動化するものは大きな助けになるでしょう。

    +0

    定理は正しいです。しかし、.Netの世界では、リンクは動的で問題なく行われます。このソリューションが必要なのは、コンパイルのステップです。 – Dykam

    +0

    もう一度お手数です:P。しかし、コンパイル時の参照(リンク)は、その特定のECMA仕様から派生したものである.Net世界で起こります。したがって、Mono、dotGnu、および.Net。 Windows自体ではありません。 – Dykam

    +0

    ちょっと、十分です。 – RBarryYoung

    25

    Dykamは説明したとおりに行うことができますが、Visual Studioはそれをやめることをブロックします。

    コマンドラインコンパイラcsc.exeを直接使用する必要があります。

    1. CSC /対象:図書館ClassA.cs

    2. CSC /対象:図書館ClassA.csクラスC:ライブラリClassB.csは

    3. CSC /ターゲットを/reference:ClassA.dll。 CS /reference:ClassB.dll

    +0

    ビジュアルスタジオでもこれを行うことができますが、非常に過酷です。基本的な方法は、#ifを使用してソリューションエクスプローラを使用して参照を削除し、3番目の手順と逆にすることです。私が考えている他の方法は、同じファイルだが異なる参照を含む3番目のプロジェクトファイルです。これは、ビルドの順序を指定できるようになります。 – Dykam

    +0

    私が知る限り、ここでそれをテストすることはできません。 – Dykam

    +0

    私はそれを本当に見たいと思います。私がここで実験したことから、あなたが参照を追加しようとすると、IDEがあなたを止めます。 –

    35

    RBarryYoungとDykamはsomethi上にある

    
    //ClassA.cs 
    namespace CircularA { 
        public class ClassA { 
        } 
    } 
    
    
    //ClassB.cs 
    using CircularA; 
    namespace CircularB { 
        public class ClassB : ClassA { 
        } 
    } 
    
    
    //ClassC.cs 
    namespace CircularA { 
        class ClassC : ClassB { 
        } 
    } 
    
    ng。 MicrosoftはILDASMを使用した内部ツールを使用してアセンブリを逆アセンブルし、すべての内部/非公開のものとメソッドの本体を削除し、ILをILASMを使用して再コンパイルして '脱水アセンブリ'またはメタデータアセンブリと呼びます。これは、アセンブリのパブリックインタフェースが変更されるたびに実行されます。

    ビルド中には、実際のメタデータアセンブリの代わりにメタデータアセンブリが使用されます。そのようなサイクルは壊れています。これを試してみてください...限り、あなたは、プロジェクト参照を使用していないとしてのVisual Studioで行うのは非常に簡単

    +1

    興味深い答え、あなたはリンクがありますか? –

    +0

    私はこのツールの外部参照を探しています。私はそれがマイクロソフトの外部に公開されているとは思えませんが、コンセプトは単純です:内部を分解して再構築してください。 –

    +0

    合意 - 興味深い答え。これをバックアップするいくつかのリンクは良いでしょう。 –

    16

    その:

    1. Visual Studioを開き
    2. "「ClassLibrary1の」& 2クラスライブラリプロジェクトを作成します。クラスライブラリ2 "。
    3. 再びステップ3.
    4. ビルドで作成したDLLを参照してClassLibrary1のへの参照を追加ClassLibrary2からステップ3
    5. で作成したDLLを参照してClassLibrary2への参照を追加ClassLibrary1のから
    6. をビルドします(注:両方のプロジェクトを変更する場合は、両方の参照を「フレッシュ」にするために2回ビルドする必要があります)

    これはそうです。しかし、真剣に...あなたは本当のプロジェクトでそれをやっていないのですか?もしあなたがそうすれば、今年はサンタさんから何かプレゼントを受けることはできません。

    0

    技術的には、これらはまったくコンパイルされておらず、手作業で組み立てられている可能性があります。これらは、結局、低レベルのライブラリです。

    +0

    本当に。それには多くの低レベルのものはなく、基本的なものだけです。何が低レベルだと思う?ランタイムとcorlibは低レベルです。相対的にまだCまたはC++で、JITには低レベルのものが含まれていると思われます。 – Dykam