Статический конструктор вызывается дважды в одном домене приложения?

Этот вопрос больше о C#, чем о log4net (я думаю).

Я создал собственный appender и позволил ему читать статическое поле, которое было предварительно установлено программой.

К моему удивлению, статическое поле было повторно инициализировано, и заданное значение не дошло до аппендера.

Я запустил debugview и увидел, что статический конструктор вызывается дважды (!). Это не должно быть возможно в том же домене приложения, верно? Только debugview выявил это, так как VS не достиг второй точки останова.

Обратите внимание, что речь не идет об избежании использования статической переменной с log4net. Я заинтересован в том, какую магию log4net использует для достижения этой цели?

Правка № 1

Привет Джон, Большой поклонник.

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

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

Кажется, есть какая-то странная вещь, которая зависает, когда среда выполнения пытается разрешить сборку log4net (как это наблюдается в режиме отладки)

Вот что я вижу в debugview:

[7756] Общее: WARN - Не удалось проанализировать версию модуля 'log4net'. Исключение: System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта. [7756] at DebuggerShared.Services.EventArgs.ModuleLoadedInDebuggerEventArgs..ctor(String modulePath, String moduleLoadMessage, Boolean isUserCode, String name, String version) [7756] Общие сведения: WARN - Не удалось проанализировать версию FollowUmon модуля. Исключение: System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта. [7756] at DebuggerShared.Services.EventArgs.ModuleLoadedInDebuggerEventArgs..ctor (String modulePath, String moduleLoadMessage, логический isUserCode, строковое имя, строковая версия)

И VS не показывает значение для пути на экране модуля отладки. Теперь, как мне удалось прийти к этой ситуации? Странно, что ему удалось загрузить сборку, но я не могу больше сказать, откуда:)

Вот такая ситуация, что если я продолжу ее модифицировать, она начнет работать как положено.

https://www.sugarsync.com/pf/D6486369_1701716_00940

Я все еще заинтересован в технических деталях, но после удаления ссылки на log4net и добавления ее снова все снова заработало. Я счастлив, что это работает, но меня беспокоит, что у меня нет подробного объяснения

Кроме того, статический конструктор * теперь вызывается дважды *, что имеет смысл, поскольку тип снова инициализируется, когда ему достается log4net.

Я думаю, что не стоит тратить больше времени на это, я думаю, что решение было в странном состоянии, и понять, что все это имеет предельную ценность. Тем не менее, если вы можете придумать что-то, чтобы объяснить это, я был бы рад здесь.

Редактировать № 2

Оказалось, что некоторые сборки действительно загружались дважды, в том числе со статическим конструктором. Позже я расскажу, как это возможно, но у меня есть обходной путь, отключив и включив Costura. Costura - это задача msbuild, которая объединяет все сборки в одну. Я не говорю, что Костура является основной причиной. Вполне возможно, что файлы csproj/sln находились в странном состоянии.

Размышляя о том, как быстрее диагностировать эту проблему в будущем, я запустил sysinternals ProcessExplorer. Теперь я ожидал, что сборки будут загружаться только один раз, но обнаружил, что они были загружены дважды. Кажется, это ошибка во время выполнения, исправленная только в.NET 4

http://forum.sysinternals.com/why-some-net-assemblies-are-duplicated-in-memory_topic15279.html https://connect.microsoft.com/VisualStudio/feedback/details/467560/clr-maps-assemblies -в-на-виртуального-адрес-пространственно-два раза

Правка № 3 Костура заставил сборки загружаться дважды. Проблема была устранена в тот же день владельцем проекта:) http://code.google.com/p/costura/issues/detail?id=17&thanks=17&ts=1328826304

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

С наилучшими пожеланиями, Том

2 ответа

Решение

Похоже, вам удалось загрузить два отдельных экземпляра log4net в то же самое AppDomain,

Один проект ссылки:

<Reference Include="log4net">
  <HintPath>..\packages\log4net.1.2.11\lib\net35-full\log4net.dll</HintPath>
</Reference>

Другой:

<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\ExternalReferences\log4net.dll</HintPath>
</Reference>

Один из них строго назван, а другой нет, в результате.net дает им разные имена. И путь подсказки тоже отличается. Также один, кажется, 1.2.10, другой 1.2.11,

попробуйте позвонить AppDomain.GetAssemblies() и проверьте, если log4net происходит дважды.

Что ж, это может быть прямой вызов инициализатора типа:

var initializer = typeof(Foo).TypeInitializer;
initializer.Invoke(null);

Тем не менее, я надеюсь, что это не так. Можете ли вы придумать короткую, но полную программу, которая демонстрирует это?

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