Подтвердить что ты не робот

.Net: Запуск кода при загрузке сборки

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

Например:

Ассамблея A не знает о сборке B, но B знает об A. Сборка A должна знать некоторые вещи о B, если B загружен. Когда сборка B загружается средой выполнения (ссылка или явная), я хочу, чтобы часть кода (статический метод или атрибут) выполнялась, которая вызывает метод в сборке A.

Основной причиной этой проблемы являются неизвестные типы, которые встречаются при сериализации типа в A, который содержит типы из B, не известные во время компиляции, в качестве интерфейсов.

4b9b3361

Ответ 2

(edit - применяется к С#; для подхода С++ см. этот ответ)

В принципе, нет: вы не можете. Это была бы огромная поверхность атаки и не допускается. Возможно, вы захотите поставить статический ctor на некоторые из типов B, которые гарантируют выполнение кода инициализации, но это о нем...

Ответ 3

Вы можете использовать статические конструкторы в .Net, но, к сожалению, они не делают то, что вы хотите. Статические конструкторы выполняются только перед использованием типа. Подробнее см. http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx.

Вы можете получить некоторый пробег от подписки на событие AppDomain AssemblyLoad. См. http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

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

Ответ 4

Вероятно, вам стоит вернуться к вашему сериализационному подходу для смягчения этой проблемы. Если вы сериализуете с помощью атрибутов ISerializable и SerializableAttribute, вы можете сделать так, чтобы график сериализации загружал сборку B, когда это необходимо, без сборки. Когда-либо нужно было явно знать о сборке B.

Ответ 5

Есть три варианта инициализации сборки .NET:

  • Вы записываете статическую функцию Init() или Main() в вашей сборке для инициализации и вызываете эту функцию путем отражения от кода С#, который загружает эту сборку.
  • Напишите управляемую сборку С++, где вы поместите свой код в DllMain(). Будьте осторожны, потому что ваш код будет выполнен в Locker Lock, где запрещено несколько вещей (например, загрузка других DLL,...). Но вы можете начать новый поток, который делает ЛЮБЫЕ вещи инициализации. (О LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx) (О DLLMain: С# в С++/CLI в C DLL System.IO.FileNotFoundException)
  • Вы собираете чистую сборку С# и изменяете скомпилированную DLL, чтобы добавить код инициализатора модуля, как описано здесь: http://einaregilsson.com/module-initializers-in-csharp/ Недостатком этого метода является то, что функция инициализации сразу не вызывается, когда сборка загружается в процесс. Но это вызвано прежде, чем что-либо еще в сборке будет впервые доступно.

Ответ 6

Используя смешанную сборку, вы можете запустить DllMain на сборку.