Как использовать расширение Ninject Conventions без ссылки на сборку (или типы внутри нее)
Извините заранее за длинный вопрос, это долго, потому что я все время копаю весь этот день.
Общая проблема:
У меня есть приложение ASP.Net MVC2 со следующими проектами: MyApp.Web, MyApp.Services, MyApp.Data.
Мы кодируем интерфейсы и используем Ninject 2 для DI/IoC.
Однако мне становится ужасно устало печатать (и забывать вводить):
Bind<ISomeService>.To<SomeService>;
Итак, зная о Ninject.Extensions.Convensions, я попытался использовать его для автоматического сканирования и регистрации модулей и простых зависимостей типа IXxxx = > Xxxx.
То, что я пробовал, работает (но этого недостаточно):
Я могу использовать следующий код для настройки Ninject, и все, кажется, подключается, как ожидалось.
public static IKernel Initialize()
{
var kernel = new StandardKernel();
kernel.Scan(a => {
a.FromAssemblyContaining<MyApp.Data.SomeDataClass>();
a.FromAssemblyContaining<MyApp.Services.SomeServiceClass>();
a.AutoLoadModules();
a.BindWithDefaultConventions();
a.InTransientScope();
});
return kernel;
}
Что я хочу сделать вместо этого:
Однако... Я бы хотел сделать это немного дальше, как мне кажется, поддерживается, но я не могу заставить его работать.
Так как наш проект MyApp.Web ничего не использует (напрямую) из MyApp.Data, я пытаюсь избежать ссылки на MyApp.Data. С приведенным выше кодом я должен ссылаться на MyApp.Data из MyApp.Web из-за ссылки времени компиляции на SomeDataClass.
Я бы предпочел указать имя сборки для Ninject для сканирования и регистрации. Кажется, что расширение Conventions поддерживает это через перегрузки From, которые берут строку (или перечисляют строки).
Что я пытался и как он ломался:
Итак, я пробовал несколько вариантов перегрузки From:
public static IKernel Initialize()
{
var kernel = new StandardKernel();
kernel.Scan(a => {
a.From("MyApp.Data");
a.From("MyApp.Services.dll");
a.From("AnotherDependency, Version=1.0.0.0, PublicKeyToken=null"); //etc., etc. with the From(...)'s
a.AutoLoadModules();
a.BindWithDefaultConventions();
a.InTransientScope();
});
return kernel;
}
Но я получаю FileNotFoundExceptions с сообщением вроде:
Не удалось загрузить файл или сборку 'файл:///C:\Program Files (x86)\Общие файлы \Microsoft Общий\DevServer\10.0\MyApp.Data "или одной из его зависимостей. Система не удается найти файл указанный.":" файл:///C:\Program Files (x86)\Общие файлы \Microsoft Общий\DevServer\10,0\
То, что я нашел, пытается решить это сам:
Я проверил источник для Ninject.Extensions.Conventions, и я признаю, что полностью потерял, как это должно работать, но я вижу, что он делает.
Сборочный сканер создает список сборок для сканирования, поскольку мы вызываем различные методы FromXXX.
Когда я вызываю метод From ( "assemblyName" ), он сначала проверяет, содержит ли список уже какие-либо сборки, где assembly.AssemblyName.Name равно имени, которое я передал (и AssemblyName.Name - это простое имя, то есть MyApp.Дата, согласно MSDN).
Поток проходит через пару неважных методов, посадку в методе FindAssemblies. Этот метод принимает имя, которое я передал (мы уже видели, это должно быть простое имя сборки). Затем он создает новое AssemblyName, с нашим переданным именем, используемым как AssemblyName.CodeBase.
Затем он пытается загрузить сборку во временный AppDomain. Это шаг, который не соответствует указанному выше исключению.
Очевидно, что путь, который он ищет, неверен, но я не могу предоставить путь через метод From(). Это тоже не работает.
Я пробовал некоторые другие методы FromXXX, но я нигде не стал и потратил слишком много времени на это уже. FromAssembliesInPath и FromAssembliesMatching также не работают, потому что, опять же, он ищет в совершенно неправильной директории.
Э-э... в чем вопрос снова:
Может ли кто-нибудь объяснить, как заставить Ninject Conventions загружать сборки по имени, не создавая ссылку на сборку и не загружая ее, указав содержащийся тип? Пожалуйста.
Я уже просматривал страницы и страницы Ninject google group, и я прочитал его только (так кажется) соответствующей документации и еще не удалось ее решить..
Ответы
Ответ 1
Этот вопрос был answerd в списке рассылки. http://groups.google.com/group/ninject/browse_thread/thread/a7f2163e060a6d64
Вкратце:
- Форма (путь) принимает путь либо относительный от рабочего каталога, либо абсолютный
- Сборка должна находиться в пути исследования, поскольку она загружается в контекст нагрузки, чтобы избежать других проблем с переключением контекста загрузки.
- Сервер разработки делает все сложнее, поскольку он копирует все сборки в свой собственный каталог, что делает невозможным использование вызывающей сборки для создания пути. Это означает единственный способ использования веб-приложений на сервере разработки.
- Мы добавим поддержку для полнофункциональных имен сборок в будущей версии, чтобы сделать это проще.
Ответ 2
Я не уверен, что это опечатка в вашем примере, но я заметил, что вы написали
kernel.Scan(a => {
a.From("MyApp.Data");
// etc.
}
Но не должно быть
kernel.Scan(a => {
a.From("MyApp.Data.dll")
// etc.
});
Потому что, если я включаю часть .dll в мой примерный проект, он работает, но если я его оставлю, я получаю исключение FileNotFoundException.