Метод C #, который выполняется после загрузки сборки - PullRequest
5 голосов
/ 24 мая 2009

Я пишу некоторую библиотеку классов C # и хочу использовать Ninject, чтобы обеспечить внедрение зависимостей для моих классов. Возможно ли, чтобы библиотека класса объявила некоторый код (метод), который будет выполняться каждый раз, когда библиотека класса загружена. Мне нужно это, чтобы определить привязки для Ninject.

Ответы [ 5 ]

6 голосов
/ 24 мая 2009

Похоже, вы ищете эквивалент DllMain в C ++. Нет способа сделать это в C #.

Не могли бы вы дать нам больше информации о вашем сценарии и о том, зачем вам нужен код для выполнения в функции стиля DllMain?

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

1 голос
/ 27 мая 2009

За последние 9 месяцев я немного использовал Ninject. Похоже, вам нужно «загрузить» ваши модули, которые есть в вашей библиотеке, в ядро ​​Ninject, чтобы зарегистрировать привязки.

Я не уверен, используете ли вы Ninject 1.x или бета-версию 2.0. Две версии работают по-разному, хотя концептуально они одинаковы. Я буду придерживаться версии 1.x для этого обсуждения. Другая часть информации, которую я не знаю, - это если ваша основная программа создает ядро ​​Ninject, а ваша библиотека просто добавляет привязки к этому ядру, или если ваша библиотека сама содержит ядро ​​и привязки. Я предполагаю, что вам нужно добавить привязки в вашей библиотеке к существующему ядру Ninject в основной сборке. Наконец, я сделаю предположение, что вы динамически загружаете эту библиотеку и она не связана статически с основной программой.

Первое, что нужно сделать, это определить модуль ninject в вашей библиотеке, в котором вы регистрируете все свои привязки - вы, возможно, уже сделали это, но стоит упомянуть. Например:

public class MyLibraryModule : StandardModule {
  public override void Load() {
    Bind<IMyService>()
      .To<ServiceImpl>();
    // ... more bindings ...
  }
}

Теперь, когда ваши привязки содержатся в модуле Ninject, вы можете легко зарегистрировать их при загрузке вашей сборки. Идея состоит в том, что после загрузки сборки вы можете отсканировать ее для всех типов, полученных из StandardModule. Если у вас есть эти типы, вы можете загрузить их в ядро.

// Somewhere, you define the kernel...
var kernel = new StandardKernel();

// ... then elsewhere, load your library and load the modules in it ...

var myLib = Assembly.Load("MyLibrary");
var stdModuleTypes = myLib
                       .GetExportedTypes()
                       .Where(t => typeof(StandardModule).IsAssignableFrom(t));


foreach (Type type in stdModuleTypes) {
  kernel.Load((StandardModule)Activator.CreateInstance(type));
}

Следует отметить, что приведенный выше код можно обобщить, чтобы загрузить несколько библиотек и зарегистрировать несколько типов. Кроме того, как я уже упоминал выше, в Ninject 2 встроена такая возможность - на самом деле она может сканировать каталоги, загружать сборки и регистрировать модули. Очень круто.

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

1 голос
/ 24 мая 2009

Вы пробовали событие AppDomain.AssemblyLoad? Он срабатывает после загрузки сборки.

AppDomain.CurrentDomain.AssemblyLoad += (s, e) =>
{
    Assembly justLoaded = e.LoadedAssembly;
    // ... etc.
};
0 голосов
/ 24 мая 2009

Можете ли вы контролировать код клиента? Если да, вместо того, чтобы пытаться творить чудеса при загрузке сборки, я бы пошел для реализации одного класса, такого как Registry, который выполняет привязки, реализуя интерфейс IRegistry. Затем во время загрузки вы можете посмотреть внедрение IRegistry в вашей сборке и запустить необходимые методы.

Вы также можете иметь атрибуты на ваших классах:

[Component(Implements=typeof(IMyDependency)]

найдите эти атрибуты и загрузите их в контейнер на стороне клиента.

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

0 голосов
/ 24 мая 2009

Насколько я знаю, ответ - нет Как я понимаю, вы хотите сконфигурировать свой контейнер IoC в своей библиотеке классов, и если это так, то это не очень хорошая идея. Если вы определяете свои привязки в своей библиотеке классов, тогда какой смысл использовать внедрение зависимостей? мы используем внедрение зависимостей, чтобы мы могли внедрять зависимости во время выполнения, тогда мы можем внедрять различные объекты в разных сценариях. Хотя лучшее место для настройки контейнера IoC - это запуск вашего приложения (так как контейнер IoC является основой для приложения :)) но он должен быть размещен в начальной загрузке, которая отвечает за запуск приложения. В простых приложениях это может быть метод Main.

...