web-dev-qa-db-ja.com

循環依存とは何ですか?どうすればそれを解決できますか?

シナリオ


私には2つ以上のプロジェクトがあるソリューションがあります。

最初のプロジェクトには、2番目のプロジェクトへのプロジェクト参照があります。 2番目のプロジェクトには、最初のプロジェクトへの参照がありません。

さて、最初のプロジェクトでは、2番目のプロジェクトの一部のクラスが継承する継承可能なクラスタイプを定義しました。

問題


明らかに、最初のプロジェクトで定義されたタイプを継承する場合は、2番目のプロジェクトで、最初のプロジェクトにプロジェクト参照を追加して、タイプを表示して続行できるようにする必要があります。

問題は、プロジェクト参照を追加しようとすると、次のエラーメッセージが表示されることです。

Circular dependency error

質問


誰かが他の簡単な言葉で私を説明することができます(おそらくコードがエラーに含まれている場合はコード例もあります)循環依存とは何ですか?そして最も重要なこと:それを解決するために何ができますか? (答える前に私の研究の最後のフレーズを読んでください)。

研究


循環依存」という言葉を聞くのは初めてです。私はMSDNのthisの記事を読みましたが、nothing

とにかく私はthisのような循環依存の多くの質問を見ました、そして私がその質問で見たものからは循環のようです依存関係とは、2つのプロジェクトが同時にそれらの間を参照できないことを意味し、これら2つのプロジェクトの一方だけが他方を参照できます。また、その質問に答えたすべての人は、「再設計が解決策です」または「循環依存は良い習慣ではありません "ただし、私の場合の再設計は、両方のプロジェクトで同じタイプを定義することを意味します。これも良い習慣ではないと思います。もちろん、単一のアセンブリを格納するためだけに追加のアセンブリ/プロジェクトを構築します。両方のプロジェクトでそのアセンブリを参照するように入力します...私が思うに最悪のアイデアです。

7
ElektroStudios

依存関係とは何ですか?

循環依存関係とは何かを理解するには、依存関係とは何か、およびそれがコンパイラーにとって何を意味するかを理解することをお勧めします。

プロジェクトがあり、クラスで次のように定義されているとします。

Public Class MyClass
    'Some code here
    Private MyString As String
    'Some code there
End Class

プロジェクトをコンパイルするとき、コンパイラは、Systemと呼ばれるDLLファイルで定義されているStringクラスを実行します。次に、そのDLLをプロジェクトにリンクします。したがって、実行時に、文字列を定義または操作するときに、System.dllがロードされてそれらが実行されます。

さて、クラスのさらに次の定義があるとしましょう。

'Some code here
Private MyObjet as CustomClass1
'Some code there

そして、CustomClass1がProject2.DLLという名前のあなたの別のプロジェクトで定義されているとしましょう。

Public Class CustomClass1
    'Your customr class code
End Class

したがって、最初のプロジェクトをコンパイルするとき、コンパイラはCustomClass1定義に遭遇し、Project2.dllにあることを認識しているため、最初のプロジェクトにその参照を追加できるようにするために、事前にProject2をコンパイルします。

それが依存関係であり、階層的であり、出発点がなければなりません。 Stringクラスでさえ他のクラスに依存しており、最終的にはすべてバイトまたはビットに依存してジョブを実行します。これは、コンピューターで実行できるのは1および0だけであるためです。 。

つまり円の部分

では、Project2に、最初のプロジェクトにリンクする参照(フィールド定義など)がある場合、どうなりますか?

  • コンパイラは最初のプロジェクトを読み取り、次にCustomClass1に遭遇します。
  • 次に、CustomClass1がそこで定義されているため、Project2のコンパイルを試みます。
  • 次に、最初のプロジェクトで定義されたクラスに実行されます
  • 最初のプロジェクトを2番目のプロジェクトにリンクするためにコンパイルしようとします
  • 次に、CustomClass1まで実行されます
  • 次に、Project2をコンパイルしようとしました
  • 私はあなたがそれを手に入れたと思います...

そのため、ある時点で、コンパイラは、実行しようとしていることを理解していないため、コンパイルできないというエラーを表示します...

はい、コンピュータはそんなに愚かです。

それを解決する方法は?

この種の問題を解決するのは難しい場合もありますが、基本的な考え方は、階層構造を構築し、基本クラス(依存関係を必要としないクラス)をまとめて、それらを構築することです。

相互に依存するすべてのクラスを取得してまとめると、アプリケーションで実行しようとすることのレイヤーが形成されます。

16
Martin Verjans

循環依存とは、プロジェクトAがプロジェクトBの何かに依存し、プロジェクトBがプロジェクトAの何かに依存する場合です。つまり、プロジェクトAをコンパイルするには、最初にプロジェクトBをコンパイルする必要がありますが、BではAをコンパイルする必要があるため、これはできません。 。これは循環依存が引き起こす問題です。

すでにビルドしたプロジェクトに循環依存関係を導入すると、標準のビルドオプションでは既存のオブジェクトファイルが削除されないため、最初にA(またはB)をビルドできるため、見つけるのが難しい場合があります。これまでソリューションをビルドしたことがない別のマシンで試した場合、またはクリーン&ビルドを実行した場合にのみ、それを見つけることができます。

私の場合、再設計するということは、両方のプロジェクトで同じタイプを定義することを意味しますが、それも良い習慣ではないと思います。

この場合、AとBの両方が依存するクラスを含む3番目のプロジェクト「C」を作成して、相互に依存しないようにする必要があります。クラスを分割するだけで、3番目のプロジェクトを作成せずに依存関係をそのように並べ替えることができます。

21
ChrisF