109

.NET BCLには、以下の間に循環参照があります。

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

これが.NETReflectorのスクリーンショットで、私が何を意味するかを示しています。

ここに画像の説明を入力してください

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

4

9 に答える 9

58

私はMonoプロジェクトがこれをどのように行うかしかわかりません。この定理は非常に単純ですが、コードが混乱します。

最初にSystem.Configuration.dllをコンパイルしますが、System.Xml.dllへの参照は必要ありません。この後、彼らはSystem.Xml.dllを通常の方法でコンパイルします。今、魔法がやってくる。System.Xml.dllへの参照が必要な部分を使用して、System.configuration.dllを再コンパイルします。これで、循環参照を使用したコンパイルが成功しました。

要するに:

  • Aは、Bを必要とするコードとBへの参照なしでコンパイルされます。
  • Bがコンパイルされます。
  • Aが再コンパイルされます。
于 2009-08-22T17:43:49.410 に答える
35

RBarryYoungとDykamは何かに取り組んでいます。Microsoftは、ILDASMを使用してアセンブリを分解し、すべての内部/プライベートコンテンツとメソッド本体を取り除き、ILを(ILASMを使用して)「脱水アセンブリ」またはメタデータアセンブリと呼ばれるものに再コンパイルする内部ツールを使用します。これは、アセンブリのパブリックインターフェイスが変更されるたびに実行されます。

ビルド中、実際のアセンブリの代わりにメタデータアセンブリが使用されます。そうすれば、サイクルが壊れます。

于 2009-08-22T17:58:05.887 に答える
27

Dykamが説明した方法で実行できますが、VisualStudioはそれを実行できません。

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

  1. csc / target:library ClassA.cs

  2. csc / target:library ClassB.cs /reference:ClassA.dll

  3. csc / target:library ClassA.cs ClassC.cs /reference:ClassB.dll


//ClassA.cs
namespace CircularA {
    public class ClassA {
    }
}


//ClassB.cs
using CircularA;
namespace CircularB {
    public class ClassB : ClassA  {
    }
}


//ClassC.cs
namespace CircularA {
    class ClassC : ClassB {
    }
}
于 2009-08-22T17:50:47.307 に答える
18

プロジェクト参照を使用しない限り、Visual Studioで行うのは非常に簡単です...これを試してください:

  1. オープンビジュアルスタジオ
  2. 2つのクラスライブラリプロジェクト「ClassLibrary1」と「ClassLibrary2」を作成します。
  3. 建てる
  4. ClassLibrary1から、手順3で作成したdllを参照して、ClassLibrary2への参照を追加します。
  5. ClassLibrary2から、手順3で作成したdllを参照して、ClassLibrary1への参照を追加します。
  6. 再ビルド(注:両方のプロジェクトに変更を加える場合は、両方の参照を「新鮮」にするために2回ビルドする必要があります)

だから、これはあなたがそれを行う方法です。しかし、真剣に...実際のプロジェクトでそれを行うことはありません!もしそうなら、サンタは今年あな​​たにプレゼントを持ってくることはありません。

于 2009-08-24T03:07:11.030 に答える
6

I guess it could be done by starting with an acyclic set of assemblies and using ILMerge to then coalesce the smaller assemblies into logically related groups.

于 2009-08-22T17:29:44.820 に答える
4

ええと、私はWindowsでそれを行ったことがありませんが、それの実用的な先祖として機能した多くのcompile-link-rtl環境でそれを行いました。最初に相互参照なしでスタブ「ターゲット」を作成してからリンクし、次に循環参照を追加してから再リンクします。リンカは通常、循環参照や後続の参照チェーンを気にせず、各参照をそれ自体で解決できることだけを気にします。

したがって、相互に参照する必要があるAとBの2つのライブラリがある場合は、次のようにしてみてください。

  1. Bへの参照なしでAをリンクします。
  2. BをAへの参照とリンクします。
  3. リンクA、参照をBに追加します。

Dykamは良い点を示しています。コンパイルであり、.Netでリンクされていませんが、原則は同じです。相互参照されたソースを、エクスポートされたエントリポイントで作成しますが、1つを除いてすべてが他のソースへの独自の参照をスタブします。アウト。そのようにそれらを構築します。次に、外部参照をスタブ解除して再構築します。これは、特別なツールがなくても機能するはずです。実際、このアプローチは、私がこれまでに試したすべてのオペレーティングシステム(そのうちの約6つ)で機能しました。明らかにそれを自動化する何かが大きな助けになるでしょうが。

于 2009-08-22T17:44:33.650 に答える
1

One possible approach is to use conditional compilation (#if) to first compile a System.dll that doesn't depend on those other assemblies, then compile the other assemblies, and at last recompile System.dll to include the parts depending on Xml and Configuration.

于 2009-08-22T17:42:06.590 に答える
0

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

于 2009-10-06T17:02:47.193 に答える