.Net: Запуск кода при загрузке сборки - PullRequest
32 голосов
/ 03 февраля 2009

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

Например:

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

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

Ответы [ 6 ]

39 голосов
/ 03 февраля 2009

CLR поддерживает инициализаторы модуля . Вам нужно взломать код C ++ / CLI или ilasm.exe, чтобы использовать их.

6 голосов
/ 03 февраля 2009

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

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

5 голосов
/ 03 февраля 2009

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

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

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

4 голосов
/ 12 февраля 2015

Существует 3 варианта инициализации сборки .NET:

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

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

0 голосов
/ 04 февраля 2010

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

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