Как получить все типы в ссылочной сборке? - PullRequest
35 голосов
/ 11 февраля 2010

По какой-то причине я не могу получить список типов в ссылочной сборке.Мало того, я даже не могу получить доступ к этой сборке.

Я пытался AppDomain.CurrentDomain.GetAssemblies(), но он возвращает только сборки, уже загруженные в память.

Я пытался Assembly.GetExecutingAssembly().GetReferencedAssemblies(), но это просто возвращает mscorlib.

Чего мне не хватает?

Ответы [ 3 ]

59 голосов
/ 11 февраля 2010

Обратите внимание, что 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, а затем, по существу, продолжить, как указано выше, для перечисления типов, которые живут в этой загруженной сборке.

0 голосов
/ 12 апреля 2018

Метод GetReferencedAssemblies в основном оптимизирует процесс обнаружения в вашей сборке, пропуская те сборки, на которые у вас нет явной ссылки в основной сборке.

Допустим, у вас есть проект B и проект C, который ссылается на проект B. Теперь вы создаете новый проект A, который имеет ссылку на C (не на B)

Когда вы вызываете Assembly.Load("C path").GetReferenceAssemblies, он вернет просто B, если вы никогда не делали ссылку на класс, enum, interface ..., который был частью сборки C.

В качестве обходного решения вы можете создавать фиктивные экземпляры классов, присутствующих в C.

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

Лично я использовал это решение на тот случай, если вам нужно разделить в проекте Core все ваши интерфейсы, а в Core.Proj1 пометить ваши классы интерфейсами, используемыми в Core, для последующего обнаружения в вашей основной сборке. Помните, что отражение влияет на производительность после загрузки нескольких сборок, поэтому не ограничивайтесь решением сделать обнаружение в каталоге и загрузить все сборки, чтобы получить нужные вам типы. Итак, с этого момента вы можете продолжить с кодом, который @jason предложил

foreach(var ....)
  Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in assembly.GetTypes()) {
        Console.WriteLine(type.Name);
0 голосов
/ 16 марта 2018

Я также попал в ситуацию, когда мне пришлось получить все сборки, которые есть в списке ссылок в 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
}
...