.NET вопрос отражения - PullRequest
6 голосов
/ 26 января 2010

Следующий код (упакован в проект Visual Studio «Консольное приложение»):

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace TestReflection
{
    class Program
    {
        static void Main(string[] args)
        {
            bool found = false;
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (assembly.GetType("System.Diagnostics.Process") != null)
                {
                    found = true;
                    break;
                }
            }
            Console.WriteLine(found);
            Console.ReadKey();
        }
    }
}

печатает «True» при запуске в режиме отладки (F5), но «False» при запуске без отладчика (Ctrl-F5). Другие классы показывают похожее поведение (System.Text.RegularExpressions.Regex), другие встречаются в обоих случаях (System.IO.File).

Я, вероятно, упускаю что-то очевидное - почему это происходит?

(то же самое происходит в Visual Studio 2005 и 2008).

UPDATE

Список найденных сборок:

Режим отладки:

mscorlib
TestReflection
System
Microsoft.VisualStudio.HostingProcess.Utilities
System.Windows.Forms

Режим работы:

mscorlib
TestReflection

Как следует из ответов, в режиме запуска сборка системы отсутствует (не загружена). Моя проблема заключалась в том, что я предполагал, что GetAssemblies () также возвращает не загруженные сборки.

Хотя это объясняет поведение System.Diagnostics.Process, почему мой код находит System.IO.File в режиме запуска и отладки?

Спасибо!

ОБНОВЛЕНИЕ 2

Я изменил код для циклического просмотра загруженных сборок и текущей сборки, собирая список сборок, на которые они ссылаются. Если после итерации загруженных сборок я не могу найти искомый тип, я начинаю загружать и проверять ссылочные сборки.

Кажется, что даже если у меня есть ссылка на System.dll в моем проекте (я просматриваю свойства ссылки 'System' в Visual Studio), мой исполняемый файл ссылается только на mscorlib.dll (согласно Reflector ).

Как добавить «реальную» ссылку на System.dll? Размещение фиктивной линии

new System.Diagnostics.ProcessStartInfo();

в начале Main делает свое дело (все работает как положено, Reflector показывает ссылки как для mscorlib.dll, так и System.dll при проверке исполняемого файла), но это взлом.

Еще раз спасибо!

Ответы [ 5 ]

11 голосов
/ 26 января 2010

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

Очевидно, что класс Diagnostics.Process не используется вашим приложением напрямую и, следовательно, не будет загружаться при работе вне отладчика.

Так почему же мы находим System.IO.File, а не System.Diagnostics.Process? Причина в том, что эти два класса, хотя они и находятся в одной и той же Системе пространства имен верхнего уровня, фактически живут в двух разных сборках. Это легко увидеть, если вы посмотрите на два класса в обозревателе объектов Visual Studio. Класс File находится в mscorlib dll, а класс Process - в System dll.

Поскольку ни одно приложение .Net не может работать без mscorlib, эта сборка будет загружена, а System.dll не загружена, поскольку вы не ссылаетесь ни на какие типы, которые живут в этой dll.

4 голосов
/ 26 января 2010

Отладчик в VS делает все возможное, чтобы обмануть вас и заставить вас думать, что ваше приложение работает так же, как и на рабочей машине. Тем не менее, он делает целую кучу вещей, которые вы не ожидаете, таких как энергичная загрузка сборок, поддержание Vars в течение долгого времени после их обычного сбора и т. Д.

В сборке выпуска CLR не будет загружать сборку в домен приложения до тех пор, пока для выполнения кода не потребуется тип или экземпляр типа. Такое поведение не гарантируется во время отладки.

Если ваш код чувствителен к этим изменениям, я бы предложил изменить его или проверить System.Diagnostics.Debugger.IsAttached.

0 голосов
/ 26 января 2010

Возможно, вам будет интересно попробовать эту строку с отладчиком и без него:

Console.WriteLine(Process.GetCurrentProcess().ProcessName);

Короче говоря, , как отмечает @Will , когда вы запускаете изнутри VS с подключенным отладчиком, вы на самом деле не запускаете 'свой exe', а скорее целую среду, в которой отладчик VS настраивает для вас. Все будет иначе.

0 голосов
/ 26 января 2010

Обычно сборки не загружаются, пока не понадобятся. При работе в режиме отладки при запуске отладчик загружает сборку Microsoft.VisualStudio.HostingProcess.Utilities. Я предполагаю, что эта сборка вызывает сборку системы и, следовательно, система загружается при запуске в режиме отладки.

0 голосов
/ 26 января 2010

Я полагаю, что некоторые сборки не имеют прямой ссылки на ваш проект, но при отладке отображаются в ваш процесс самим отладчиком.

Убедитесь, что искомые сборки находятся в References для вашего проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...