Как ссылки расположены в.NET?

Какой процесс.NET использует для поиска ссылочной сборки во время выполнения, и отличается ли он от процесса, используемого для поиска ссылочной сборки во время компиляции? Меня особенно интересуют местоположения, в которых производится поиск, и порядок их поиска, а также любые параметры / настройки конфигурации, которые могут повлиять на результат.

1 ответ

Решение

Существует три типа ссылок, которые можно сделать в приложении.NET. Этот ответ будет охватывать только первые два в списке ниже.

  1. Ссылки на файлы.
  2. Ссылки на проекты
  3. Сервисные ссылки.

Каждая ссылка должна быть решена. Разрешение ссылок - это процесс поиска конкретного экземпляра ссылки в виде файла. Ссылки на проекты разрешаются так же, как и ссылки на файлы. Ссылка на проект позволяет просто ссылаться на сборки, которые еще не существуют (потому что это результат процесса сборки).

Важно понимать, что эталонное разрешение происходит как во время компиляции, так и во время выполнения, и процесс для каждого из них совершенно различен. Неспособность понять этот момент может привести к бесконечной головной боли. Поверь мне, я знаю.

Разрешение эталонного времени выполнения (или связывание)

Когда приложение вызывается, оно должно быть загружено в память. Если приложение использует объекты в другой сборке, эта сборка также должна быть загружена в память..NET Framework использует следующий процесс для этого.

  1. Определить версию ссылочной сборки.
    • Версия указанной сборки записывается в манифест приложения во время компиляции. Эта версия будет использоваться, если не переопределена в конфигурации.
      • Приложение /web.config
      • Политика публикации (переопределяет application/web.config)
      • machine.config (переопределяет политику публикации и application/web.config)
  2. Если сборка была ранее загружена, то повторно использовать из кеша.
  3. Если указано строгое имя, выполните поиск в GAC.
  4. зонд
    • Если указан элемент codebase, используйте.
      • Ошибка привязки, если не найдена.
      • Ошибка привязки, если версия, культура или открытый ключ не совпадают.
    • Поиск базового пути приложения. Совпадает по простому имени и завершается неудачно, если первое совпадение неверно.
      • Если культура не указана, выполните поиск в корне, затем root/[имя сборки]
      • Если указана культура, найдите root/[culture], затем root/[culture]/[имя сборки].
      • Если web/app.config указывает элемент исследования, пути поиска в privatePath. Пути должны быть относительно корня приложения.

Для получения дополнительной информации см. http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=vs.110%29.aspx.

Разрешение по времени компиляции

Разрешение времени компиляции происходит в MSBuild во время процесса сборки. MSBuild - это механизм сборки, используемый как Visual Studio, так и TFS. Обратите внимание, что для приложений ASP.NET существует дополнительный шаг компиляции, который выполняется для динамических компонентов (aspx, asc, asax, cshtml и т. Д.) При первом обращении к ним. Эталонное разрешение для этих двух сценариев описано ниже.

MSBuild

Разрешение сборки происходит в целевом объекте ResolveAssemblyReferences MSBuild. Эта цель вызывает задачу ResolveAssemblyReference, передавая значение AssemblySearchPaths параметру SearchPaths, которому присваивается значение следующим образом.

<PropertyGroup>
        <!--
        The SearchPaths property is set to find assemblies in the following order:

            (1) Files from current project - indicated by {CandidateAssemblyFiles}
            (2) $(ReferencePath) - the reference path property, which comes from the .USER file.
            (3) The hintpath from the referenced item itself, indicated by {HintPathFromItem}.
            (4) The directory of MSBuild's "target" runtime from GetFrameworkPath.
                The "target" runtime folder is the folder of the runtime that MSBuild is a part of.
            (5) Registered assembly folders, indicated by {Registry:*,*,*}
            (6) Legacy registered assembly folders, indicated by {AssemblyFolders}
            (7) Resolve to the GAC.
            (8) Treat the reference's Include as if it were a real file name.
            (9) Look in the application's output folder (like bin\debug)
        -->
    <AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == ''">
      {CandidateAssemblyFiles};
      $(ReferencePath);
      {HintPathFromItem};
      {TargetFrameworkDirectory};
      {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
      {AssemblyFolders};
      {GAC};
      {RawFileName};
      $(OutDir)
    </AssemblySearchPaths>

Здесь много чего происходит, и я не претендую на то, что понимаю все это, но я постараюсь указать на важные части.

  1. Наиболее распространенные места для поиска ссылки (в порядке поиска)
    • Файлы, добавленные в проект вручную (например, /lib/coollib.dll>
    • Местоположение указывается путем подсказки.
    • GAC
    • Путь вывода приложения.
  2. Ссылки, помеченные как Copy Local = true, копируются в выходной путь приложения после компиляции. Это означает, что значение этого параметра не влияет на процесс разрешения ссылок для MSBuild. Обратите внимание, что параметр "Копировать локальный интерфейс" отображается на <private> элемент в файле проекта.
  3. MSBuild всегда будет пытаться использовать последнюю версию, доступную для данной сборки, если не указана конкретная версия = true. Значение по умолчанию для этого параметра - false, что означает, что при поиске в GAC всегда будет использоваться самая последняя версия DLL независимо от версии, указанной в определении проекта.

ASP.NET Runtime Compiler

Если предварительно не скомпилировано в выходную папку проекта с использованием параметра предварительной компиляции во время сборки, весь динамический контент (aspx, asc, asax, cshtml и т. Д.) Компилируется один раз во время выполнения при первом обращении к приложению. Этот динамический контент также может зависеть от других сборок. Элемент system.web > compilation > сборка используется, чтобы сообщить компилятору времени выполнения ASP.NET об этих зависимостях, чтобы он мог ссылаться на них.

Компилятор времени выполнения ASP.NET будет искать следующие ссылки, чтобы найти эти ссылки.

  1. Кэш приватной сборки приложений (он же PAC), который является папкой /bin.
  2. GAC (если ссылка указана с использованием строгого имени).

Обратите внимание, что по умолчанию корневой web.config ссылается на несколько системных сборок и все сборки в PAC с использованием подстановочного синтаксиса. Это означает, что вам редко понадобится явно добавлять ссылки вручную в элемент system.web > compilation > сборки. Во многих случаях вы можете и должны полностью удалить элемент. Он должен содержать только ссылки на сборки, хранящиеся в GAC. Использование Copy Local = true - рекомендуемый подход для включения ссылок не GAC, требуемых компилятором времени выполнения ASP.NET.

Также обратите внимание, что многие незначительные ошибки могут возникать, если вы используете элемент system.web > compilation > сборки, чтобы указать конкретный номер версии, используя строгое имя сборки. Компилятор времени выполнения ASP.NET попытается скомпилировать, используя указанную вами версию. Это может вызвать проблемы, если не динамические компоненты приложения были скомпилированы с другой версией сборки на этапе компиляции MSBuild. Это часто имеет место, потому что MSBuild будет использовать последнюю найденную версию и только точную версию, если вы установите конкретную версию = true.

Дополнительные ресурсы:

http://jack.ukleja.com/diagnosing-asp-net-page-compilation-errors/ http://blog.fredrikhaglund.se/blog/2008/02/23/get-control-over-your-assembly-dependencies/ https://dhakshinamoorthy.wordpress.com/2011/10/01/msbuild-assembly-resolve-order/ http://www.beefycode.com/post/resolving-binary-references-in-msbuild.aspx

Другие вопросы по тегам