web-dev-qa-db-ja.com

参照されたアセンブリのすべてのタイプを取得するにはどうすればよいですか?

何らかの理由で、参照されているアセンブリの型のリストを取得できないようです。それだけでなく、この参照されたアセンブリに到達することすらできないようです。

AppDomain.CurrentDomain.GetAssemblies()を試しましたが、メモリに既に読み込まれているアセンブリのみが返されます。

私はAssembly.GetExecutingAssembly().GetReferencedAssemblies()を試しましたが、これはmscorlibを返すだけです。

何が欠けていますか?

35
AngryHacker

Assembly.GetReferencedAssembliesには、アセンブリでそのアセンブリの型を実際に使用する場合(または使用する型がそのアセンブリの型に依存する場合)にのみ、特定のアセンブリが含まれることに注意してください。 Visual Studioの参照リストにアセンブリを含めるだけでは十分ではありません。多分これはあなたが期待するものからの出力の違いを説明していますか?私は、リフレクションを使用してVisual Studioの参照のリストにあるすべてのアセンブリを取得できることを期待している場合は不可能であることに注意してください。アセンブリのメタデータには、特定のアセンブリが依存していないアセンブリに関する情報は含まれていません。

つまり、参照されるすべてのアセンブリのリストを取得したら、次のようなものを使用して、それらのアセンブリのすべての型を列挙できます。

foreach (var assemblyName in Assembly.GetExecutingAssembly().GetReferencedAssemblies()) {
    Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in Assembly.GetTypes()) {
        Console.WriteLine(type.Name);
    }
}

Visual Studioで参照されるアセンブリが必要な場合は、csprojファイルを解析する必要があります。そのためには、ItemGroup要素を含むReference要素を確認してください。

最後に、アセンブリが存在する場所がわかっている場合は、Assembly.LoadFileを使用してアセンブリをロードし、基本的に上記の手順に進んで、ロードされたアセンブリに存在するタイプを列挙できます。

61
jason

また、Visual Studioの参照リストにあるすべてのアセンブリを取得しなければならない状況にも陥りました。

私はそれを成し遂げるために以下の回避策を使用しました。

var path = AppContext.BaseDirectory;  // returns bin/debug path
var directory = new DirectoryInfo(path);

if (directory.Exists)
{
    var dllFiles = directory.GetFiles("*.dll");  // get only Assembly files from debug path
}
1
Deepak Ageeru

メソッドGetReferencedAssembliesは、基本的にアセンブリの検出プロセスを最適化し、メインアセンブリに明示的な参照がないアセンブリをスキップします。

プロジェクトBと、プロジェクトBを参照しているプロジェクトCがあるとします。次に、Cへの参照(Bではない)を持つ新しいプロジェクトAを作成します。

Assembly.Load("C path").GetReferenceAssembliesを呼び出すと、Cアセンブリの一部であるクラス、列挙型、インターフェイス...への参照を作成したことがない場合は、Bのみが返されます。

回避策として、Cに存在するクラスのダミーインスタンスを作成できます。

Assembly.C.Class1 dummyInstance = new Assemply.C.Class1();

個人的には、Coreプロジェクトですべてのインターフェイスを分離する必要がある場合、およびCore.Proj1でコアに使用されるインターフェイスを使用してクラスにフラグを付け、後でメインアセンブリで検出する必要がある場合に、このソリューションを使用しました。複数のアセンブリをロードすると、リフレクションはパフォーマンスに影響を与えることに注意してください。ディレクトリで検出を行い、すべてのアセンブリをロードして必要なタイプを取得するソリューションで終わらせないでください。その時点から、@ jasonが提案したコードを続行できます

foreach(var ....)
  Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in Assembly.GetTypes()) {
        Console.WriteLine(type.Name);
0
Zinov